[Pharo-project] building and installing a morph in the background
Hi, I am trying to build a complex morph and install it in another morph in a background process such that it does not impact the rest of the user interface. After a discussion with Igor, I got to the code below (similar to what can be found in CodeAnnotationPane). However, it still does not seem to have the desired effect as the main ui still appears to be blocked. Can anyone see any problem with the code? The code can be found in the latest version of Glamour. Cheers, Doru GLMWatcherWindow>>addContent: aBlockWhoseValueReturnsAMorph | newMorph | "if we are still rendering some contents for another watcher, we stop and replace with the current request" process ifNotNil: [ process terminate ]. process := nil. process := [ WorldState addDeferredUIMessage: [ newMorph := aBlockWhoseValueReturnsAMorph value. self contentsMorph removeAllMorphs; addMorph: newMorph fullFrame: (LayoutFrame fractions: (0@0 corner: 1@1)) ] ] newProcess. process priority: Processor userBackgroundPriority. process resume -- www.tudorgirba.com "Problem solving should be focused on describing the problem in a way that makes the solution obvious."
On 27 May 2012 01:58, Tudor Girba <tudor@tudorgirba.com> wrote:
Hi,
I am trying to build a complex morph and install it in another morph in a background process such that it does not impact the rest of the user interface. After a discussion with Igor, I got to the code below (similar to what can be found in CodeAnnotationPane).
However, it still does not seem to have the desired effect as the main ui still appears to be blocked. Can anyone see any problem with the code?
The code can be found in the latest version of Glamour.
Cheers, Doru
GLMWatcherWindow>>addContent: aBlockWhoseValueReturnsAMorph     | newMorph |
    "if we are still rendering some contents for another watcher,     we stop and replace with the current request"     process ifNotNil: [ process terminate ].     process := nil.
    process := [         WorldState addDeferredUIMessage:  [             newMorph := aBlockWhoseValueReturnsAMorph value.             self contentsMorph                 removeAllMorphs;                 addMorph: newMorph fullFrame: (LayoutFrame fractions: (0@0 corner: 1@1))         ]     ] newProcess.     process priority: Processor userBackgroundPriority.     process resume
Sure thing, because you still building your morph in UI thread (inside a block which you pass to addDeferredUIMessage. To make it clear, WorldState addDeferredUIMessage: can be rephrased as: WorldState evaluateThisBlockInUIProcess: So, moving newMorph := aBlockWhoseValueReturnsAMorph value. outside of this block will do the thing.
-- www.tudorgirba.com
"Problem solving should be focused on describing the problem in a way that makes the solution obvious."
-- Best regards, Igor Stasenko.
Hi Igor, I tried adding it outside of the addDeferredUIMessage as well: process := [ newMorph := aBlockWhoseValueReturnsAMorph value. WorldState addDeferredUIMessage: [...] ] newProcess. However, the problem seems to be the same. If you, or someone else, would have time to look into it, here is how to reproduce: Download the latest moose image: http://ci.moosetechnology.org/job/moose-latest-dev/lastSuccessfulBuild/artif... Run: | browser | browser := GLMTabulator new. browser column: #numbers. browser transmit to: #numbers; andShow: [:a | a list display: [:x | 1 to: x] ]. browser transmit from: #numbers; toWatcher; andShow: [:a | a list title: [:x | 'Large presentation for ', x asString]; display: [:x | x to: (x * 1000)] ]. (browser openOn: 42) left: 0; top: 0. (GLMWatcherWindow uniqueInstance toggleOpen) left: 300; top: 100 . Time millisecondsToRun: [ (browser panes first port: #selection) value: 10 ] . The relevant code is in GLMWatcherWindow>>addContent: The interesting thing is that if I print the amount of time, it goes fast (close to 0s), but the UI is still blocked. Cheers, Doru On 27 May 2012, at 04:23, Igor Stasenko wrote:
On 27 May 2012 01:58, Tudor Girba <tudor@tudorgirba.com> wrote:
Hi,
process := [ WorldState addDeferredUIMessage: [ newMorph := aBlockWhoseValueReturnsAMorph value. self contentsMorph removeAllMorphs; addMorph: newMorph fullFrame: (LayoutFrame fractions: (0@0 corner: 1@1)) ] ] newProcess.
Sure thing, because you still building your morph in UI thread (inside a block which you pass to addDeferredUIMessage.
To make it clear, WorldState addDeferredUIMessage: can be rephrased as:
WorldState evaluateThisBlockInUIProcess:
So, moving newMorph := aBlockWhoseValueReturnsAMorph value. outside of this block will do the thing.
-- www.tudorgirba.com "Speaking louder won't make the point worthier."
i think there is some mistake in event wiring.. i cannot tell much, because i don't understand the glamour models.. but what i found strange is that i get large pause before i got halt in actOnMatchingPresentationsChanged: it looks like the same event goes twice (or there two kinds of events) and you model tries to update the detal list bypassing (or in addition) to the #actOnMatchingPresentationsChanged: To reproduce my observations try do following: - evaluate the doit which you gave above , so you have two windows open. Now click in a browser list, to set the initial selection. Now go to #actOnMatchingPresentationsChanged and put halt there actOnMatchingPresentationsChanged: anAnnouncement +++ self halt. GLMWatcherWindow uniqueInstance addContent: [ self renderObject: anAnnouncement pane ] Now click on list again to change the selection. You can observe a huge pause before you got halt. So, apparently the logic in #addContent: has nothing to do with the blocking you still observe. (btw in image which you give in link the morph generation is still inside of #addDeferredUIMessage, i , of course moved it outside before trying things). P.S. btw, did i told you that i don't like #suspendAllWhile: in announcer? :) The point is: if you need things like that, then you doing something wrong. -- Best regards, Igor Stasenko.
Hi, Thanks, Igor. Indeed, something is strange. And indeed, you were obviously right about not building the morph inside the addDeferredUIMessage block. It's published now. I built a test to show the behavior. It does not rely on a Glamour mechanism, but it does use the GLMWatcherWindow. Perhaps it is useful for other people: ----- GLMWatcherWindow uniqueInstance toggleOpen. GLMWatcherWindow uniqueInstance addContent: [ RectangleMorph new color: Color transparent ]. "just to make sure it's gray" (Delay forMilliseconds: 500) wait. "this is just to simulate an initial request for a blue rectangle. it has a slight delay." GLMWatcherWindow uniqueInstance addContent: [ (Delay forMilliseconds: 1000) wait. RectangleMorph new color: Color blue ]. "this is for simulating an override of the previous request. the delay is longer to ensure that blue can appear in case the process is not terminated properly" GLMWatcherWindow uniqueInstance addContent: [ (Delay forMilliseconds: 5000) wait. RectangleMorph new color: Color red ] ----- So, the basic question is now solved. Thanks. I will look into the Glamour-related problem. I might need some more help there :) Cheers, Doru p.s. I know you do not like suspendAllWhile:, but I think there are scenarios in which it is useful. I will get back to this in a separate thread a bit later On 27 May 2012, at 18:30, Igor Stasenko wrote:
i think there is some mistake in event wiring.. i cannot tell much, because i don't understand the glamour models..
but what i found strange is that i get large pause before i got halt in actOnMatchingPresentationsChanged:
it looks like the same event goes twice (or there two kinds of events) and you model tries to update the detal list bypassing (or in addition) to the #actOnMatchingPresentationsChanged:
To reproduce my observations try do following: - evaluate the doit which you gave above , so you have two windows open. Now click in a browser list, to set the initial selection.
Now go to #actOnMatchingPresentationsChanged and put halt there
actOnMatchingPresentationsChanged: anAnnouncement
+++ self halt. GLMWatcherWindow uniqueInstance addContent: [ self renderObject: anAnnouncement pane ]
Now click on list again to change the selection. You can observe a huge pause before you got halt. So, apparently the logic in #addContent: has nothing to do with the blocking you still observe. (btw in image which you give in link the morph generation is still inside of #addDeferredUIMessage, i , of course moved it outside before trying things).
P.S. btw, did i told you that i don't like #suspendAllWhile: in announcer? :) The point is: if you need things like that, then you doing something wrong.
-- Best regards, Igor Stasenko.
-- www.tudorgirba.com "To utilize feedback, you first have to acquire it."
participants (2)
-
Igor Stasenko -
Tudor Girba