Ben Coman wrote:
Tudor Girba wrote:
Hi Ben,
On 1 Mar 2012, at 19:08, Ben Coman wrote:
> Very
much looking forward to a further Glamour-Magritte example.
>
>
>
It's in the repository. You can also find it in the latest Moose dev
build, although this will be on Pharo 1.4:
http://ci.moosetechnology.org/job/moose-latest-dev/lastSuccessfulBuild/arti…
Thanks Tudor. I added having a list view and details pane (image attached)
and uploaded to
http://www.squeaksource.com/Glamour as Glamour-Examples-BenComan.227. I
hope you like it. Those small number of lines are a testament to the power of both
Glamour and Magritte, and a minor achievement in my learning of them. Things are slowly
falling into place.
Excellent.
However I've broken starting it from the
examples browser, so use the method comment - and hopefully the fix is obvious to you
since I could not work it out.
But, it does work already :). My guess is that you tried to work from an opened examples
browser, but the current implementation does not reload the code of the pragma (which
means that you were probably running the new code with the old setup).
You are right. It works in a newly opened examples browser.
Anyway, if you start a new examples browser it
will work as expected. Nice job.
Also as I mentioned above, the <Cancel>
button does not perform as I expect, which would be to revert back to the original data.
Indeed, this is a good point. Would you like to give it a try to fix this? If you need
help, just ask and I try to answer. Like that you learn the internals of Glamour (they are
not that complicated)
The relevant code is in:
- GLMMagrittePresentation
- GLMMorphicMagritteRenderer
Some help would be appreciated. I would
like to use this to browse and
modify some electrical power data for my Master project. I've spent
about 10 hours at it and has some success, but need a more experienced
eye to look it over. I documented my investigation in detail (if a bit
scrappy) since this forced me to consider each part separately and did
help improve my understanding of the system. Perhaps it even might be a
good walk through for other.
There is a second problem to the one above. The <save> button does work
okay such that I change change person and back again and any change I
made remains. However a change to the Name attribute in the #details
pane is not reflected in the #list pane. I tried to track this down as
well. I was having trouble determining which object were copies or not
so I added the following code to the example...
----------------
Object subclass: #GLMMagrittePersonExample
instanceVariableNames: 'name address'
classVariableNames: 'Sample1'
poolDictionaries: ''
category: 'Glamour-Examples'
GLMMagrittePersonExample>>sample1
Sample1 ifNil:
[
Sample1 := OrderedCollection new.
Sample1 add: (GLMMagrittePersonExample new name: 'William
Shakespeare' ; address: 'Stratford-upon-Avon' ).
Sample1 add: (GLMMagrittePersonExample new name: 'Victor Hugo' ;
address: 'Besançon' ).
Sample1 add: (GLMMagrittePersonExample new name: 'Mark Twain' ;
address: 'Florida' ).
Sample1 add: (GLMMagrittePersonExample new name: 'Banjo
Paterson' ; address: 'Narrambla' ).
].
^Sample1
GLMMagrittePersonExample>>identityInSample1
^ self class sample1 includes: self.
GLMMagrittePersonExample>>printOn: aStream
aStream nextPutAll: '('.
self name printOn: aStream.
aStream nextPutAll: ','.
self address printOn: aStream.
aStream nextPutAll: ')'.
self identityInSample1
ifTrue: [ aStream nextPutAll: ' #original# ']
ifFalse: [ aStream nextPutAll: ' #copy# '].
super printOn: aStream.
-------------------
Now for reference below, here is GLMBasicExamples>>magritte
001 magritte
002 <glmBrowser: 'Magritte presentation' input:
'GLMMagrittePersonExample sample1'>
003 "self new magritte openOn: GLMMagrittePersonExample sample1"
004 | browser |
005 browser := GLMTabulator new.
006 browser column: #list; column: #detail.
007 browser transmit to: #list ; andShow: [ :a |
008 self halt.
009 a list
010 format: [ :aPerson | self halt. aPerson name ] ].
011 browser transmit from: #list ; to: #detail ; andShow: [ :a |
012 self halt.
013 a magritte
014 title: 'Details';
015 act: [:magritte | self halt. magritte entity explore ]
016 icon: GLMUIThemeExtraIcons glamorousInspect
017 entitled: 'Explore';
018 description: [:aPerson | self halt. aPerson
magritteDescription] ].
019 ^ browser
I was having trouble following what was happening, so I went overboard
and put a 'self halt' at the start of EVERY method and block associated
with GLMMagrittePresentation & GLMMorphicMagritteRenderer, so then...
(1) From Workspace... <DoIt> GLMBasicExamples new magritte openOn:
GLMMagrittePersonExample sample1
(2) hits the first halt in line 008.
This stores the block from line 010 used later in (5)
(3) <Proceed> to the halt in line 012.
This stores the blocks on lines 015 & 018 for later use.
(4) <Proceed> to the halt in #GLMMagrittePresentation>>description: .
This just stores a block into ivar magritteDescription for later use.
(5) <Proceed> to the halt on line 010 where the four data values for
the #list pane are being readied for display.
Here aPerson is #original#.
(6) <Proceed> four times to...
update the display with Glamorous Browser appearing with four items in
#list pane and the #details pane blank.
(7) Clicking on a data item proceeds to the halt in
GLMMagrittePresentation>>renderGlamorouslyOn:
At the bottom of the call stack I see the very first call after
MessageSend>>valueWithArguments is
GLMMorphicPaneRenderer>>actOnMatchingPresentationChanged and that its
parameter anAnnouncement is aGLMMatchingPresentationsChanged (pane = a
GLMPane(386924544 detail)). I don't really understand announcements yet
but I wonder if I need to somehow to fire off a similar announcement to
refresh the display after I press the <cancel> button.
(8) <Proceed> to halt in GLMMorphicMagritteRenderer>>render
This is actually only a few debug-steps on from (7) we have (
aMagrittePresentation on: GLMPresentationUpdated send:
#actOnPresentationUpdated: to: self.)
and I wonder if this needs to match (7) ????
(9) <Proceed> to halt in GLMMorphicMagritteRenderer>>magritteMorphFrom:
This is actually only a few debug-steps on from (8).
toShow:= is #original#. This was a surprise (I'm not sure why) but
is a good sign.
Stepping through the line description:= leads directly (10) or
alternatively...
(10) <Proceed> to the halt in GLMMagrittePresentation>>magritteDescription.
This returns the block [:aPerson | self halt. aPerson
magritteDescription] stored by (3) from line 018
Stepping through the evaluation of the block leads to (11),
alternatively...
(11) <Proceed> to the halt in line 018.
Here aPerson is still #original#
(9b) Continuing to step through returns to
GLMMorphicMagritteRenderer>>magritteMorphFrom:
Inspecting magritteDescriptionMorph after it is assigned shows it
contains a memento, that when inspected (and left open which I shall
refer to as memento1) shows instant variables
memento1.model = ('William Shakespeare','Stratford-upon-Avon')
#original# a GLMMagrittePersonExample
It is interesting that I can now see the #original# has carried
through to this point. I had assumed that some of my non-update
problems had been to do with operating on copies of copies.
memento1.cache = copies of each attribute of
GLMMagrittePersonExample as
(a MAStringDescription label: 'Name' comment:
nil->'William Shakespeare')
(a MAStringDescription label: 'Address' comment:
nil->'Stratford-upon-Avon')
memento1.original = copies of each attribute of
GLMMagrittePersonExample
(a MAStringDescription label: 'Name' comment:
nil->'William Shakespeare')
(a MAStringDescription label: 'Address' comment:
nil->'Stratford-upon-Avon')
(12) At any point you can <Proceed> to...
update the display with the #details pane filled in.
(13) Altering the Name attribute to be 'xxxxxx' (and saving with
<ctrl-s>) I observe
memento1.cache has changed to (a MAStringDescription label:
'Name' comment: nil->'xxxxxx')
with no change in memento1.model or memento1.original.
(14) Then clicking <cancel> proceeds to the halt in
GLMMagrittePresentation>reactOnAnswerFor:
Looking one level back up the call stack I see that this is called
from the block stored by #onAnswer: in GLMMorphicMagritteRenderer. I
think this is where the code might need changing.
GLMMagrittePresentation>reactOnAnswerFor: doesn't seem to do stuff
all. It just returns some data, which if you follow through to the when
the debugger closes, seems to just get thrown away.
Prior to this point, memento1.cache has already changed back to (a
MAStringDescription label: 'Name' comment: nil->'William
Shakespeare').
This would appear to have occurred several level back up the call
stack in MASilentContainerMorph>>cancel with a (self reset)
So it would seem that we just need to notify the display to redraw.
GLMMagrittePresentation>reactOnAnswerFor: has self of (a
GLMMagrittePresentation(id=685506560 title=Details pane=a
GLMPane(386924544 detail)))
which matches the pane from (7). If I use World > Tools > Finder to
search source for 'GLMMatchingPresentationsChanged' I find
GLMMorphicPaneRenderer>>render:
which has aPane on: GLMMatchingPresentationsChanged send:
#actOnMatchingPresentationChanged: to: self.
so in the debugger I went to try...
pane on: GLMMatchingPresentationsChanged send:
#actOnMatchingPresentationChanged: to: XXXX.
but I could not work out what XXXX should be since it seemed like it
should be the renderer and I did not have that here.
But then looking around some more I see the parent class
GLMPresentation has method 'update'
so from the debugger 'self update' returned the display to show
'William Shakespeare'.
So inthe end I added 'self update' to the start of
GLMMagrittePresentation>>reactOnAnswerFor: as follows...
reactOnAnswerFor: aValue
self update.
^ answerBlock glamourValue:
(aValue asGlamorousMultiValue,
self asGlamorousMultiValue,
self entity asGlamorousMultiValue)
and now the <cancel> button works as expected. However I still don't
know what reactOnAnswerFor is meant to do, or if there
is a more appropriate way of achieving this. Please let me know.
I also haven't had any success getting the #list pane to refresh when a
change is saved on the #detail pane. Any assistance will be greatly
appreciated.
cheers, -ben