#queryCommand: not called if a button's command changes

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
21 messages Options
12
Reply | Threaded
Open this post in threaded view
|

#queryCommand: not called if a button's command changes

Yar Hwee Boon-3
Hi all

I have a shell with 6 buttons, if I implement the shell's #queryCommand:  
method as

MyShell>>queryCommand: query
        Transcript print: query commandSymbol; cr.
        super queryCommand: query.
        "etc etc"

I see the following in the system transcript:

        #updateCSS
        #getCSS
        #addTag
        #addSection
        #removeSectionOrTag1
        #rename

If I then changed the button with command #removeSectionOrTag1 to  
#removeSectionOrTag. I only see

        #updateCSS
        #getCSS
        #addTag
        #addSection
        #rename

Note that when the shell first appears, I do see #removeSectionOrTag being  
printed out, but after that, whenever I click on the shell to activate it,  
#removeSectionOrTag no longer appears. I can't reproduce it if I create a  
fresh shell with the same commands. Did I miss something obvious?

--
Regards
Hwee Boon
MotionObj


Reply | Threaded
Open this post in threaded view
|

Re: #queryCommand: not called if a button's command changes

Chris Uppal-3
Yar Hwee Boon wrote:

> If I then changed the button with command #removeSectionOrTag1 to
> #removeSectionOrTag. I only see

I may be misunderstand what you are trying to do, but I don't think that the
MVP framework is really designed to allow you to change the command of a button
or menu item.  At least, its not something that I've ever heard of anyone
doing, so even if /it/ is supposed to work, it wouldn't be surprising if it
turned out to be buggy.

In one case where I wanted to do something similar (a VCR-style control panel
where the 'Play' button would change into a 'Pause' button while the animation
was running), I just used two separate buttons in the same place and #show /
#hide them appropriately.

I don't know if its at all relevant, but I suppose it might be worth
remembering that you can change the text of a button or menu item from the
corresponding queryCommand: with
    aCommandQuery text: '...whatever...'.

    -- chris


Reply | Threaded
Open this post in threaded view
|

Re: #queryCommand: not called if a button's command changes

Yar Hwee Boon-3
On Thu, 8 Jul 2004 09:32:12 +0100, Chris Uppal  
<[hidden email]> wrote:

> Yar Hwee Boon wrote:
>
>> If I then changed the button with command #removeSectionOrTag1 to
>> #removeSectionOrTag. I only see
>
> I may be misunderstand what you are trying to do, but I don't think that

Ah.. sorry, rather, I must have not communicated my problem properly. What  
I mean was I changed the command from within the view composer and #show  
the shell again. I didn't try to change it during runtime. But see below  
for the discrepancy, in the 2nd case #removeSectionOrTag is not printed  
out, meaning that #queryCommand: was sent for that particular button  
merely because I changed the command. Which was quite of weird (to me at  
least). Sorry I can't give specific code, because I can't reproduce this  
with another class.


With #removeSectionOrTag1:

        #updateCSS
        #getCSS
        #addTag
        #addSection
        #removeSectionOrTag1
        #rename

With #removeSectionOrTag:

        #updateCSS
        #getCSS
        #addTag
        #addSection
        #rename

--
Regards
Hwee Boon
MotionObj


Reply | Threaded
Open this post in threaded view
|

Re: #queryCommand: not called if a button's command changes

Bill Dargel
Yar Hwee Boon wrote:
> What
> I mean was I changed the command from within the view composer and #show
> the shell again. I didn't try to change it during runtime. But see below
> for the discrepancy, in the 2nd case #removeSectionOrTag is not printed
> out, meaning that #queryCommand: was sent for that particular button
> merely because I changed the command.

I'm a little fuzzy on how the whole routing of CommmandQuery's work, but
I had a thought. I think you're saying that, using #removeSectionOrTag1
it shows up in the #queryCommand: for your shell, but using
#removeSectionOrTag it doesn't. Could it be that #removeSectionOrTag is
already being handled by some lower level presenter that comes earlier
in the command routing, such that that particular name doesn't make it
up to your shell?

-------------------------------------------
Bill Dargel            [hidden email]
Shoshana Technologies
100 West Joy Road, Ann Arbor, MI 48105  USA


Reply | Threaded
Open this post in threaded view
|

Re: #queryCommand: not called if a button's command changes

Yar Hwee Boon-3
On Thu, 08 Jul 2004 16:16:11 -0400, Bill Dargel <[hidden email]>  
wrote:

> I'm a little fuzzy on how the whole routing of CommmandQuery's work, but
> I had a thought. I think you're saying that, using #removeSectionOrTag1
> it shows up in the #queryCommand: for your shell, but using
> #removeSectionOrTag it doesn't.

Yup.

> Could it be that #removeSectionOrTag is
> already being handled by some lower level presenter that comes earlier
> in the command routing, such that that particular name doesn't make it
> up to your shell?

I browsed for references of #removeSectionOrTag and didn't find any.

--
Regards
Hwee Boon
MotionObj


Reply | Threaded
Open this post in threaded view
|

Re: #queryCommand: not called if a button's command changes

Chris Uppal-3
In reply to this post by Bill Dargel
Bill Dargel wrote:

> Could it be that #removeSectionOrTag is
> already being handled by some lower level presenter that comes earlier
> in the command routing, such that that particular name doesn't make it
> up to your shell?

That's my thought too.

It's worth adding that it's not just Presenters that are on the default command
route, but the Views are as well.  Also, in certain circumstances, the Model
and even the Comand itself can be involved.  The command routing concept is one
of the subtlest in Dolphin MVP; it's quite complex but very powerful.  The
thing is that it works so well most of the time that you tend to forget that
its happening at all.

If the button is enabled, then one way to find out what's going on would be to
find any implementation of #removeSelectorOrTag in the image, put breakpoints
in all of them, then click on the button.  Then from the debugger it should be
possible to work out what is actually handing it, and how the command ends up
being routed there.

    -- chris


Reply | Threaded
Open this post in threaded view
|

Re: #queryCommand: not called if a button's command changes

Chris Uppal-3
In reply to this post by Yar Hwee Boon-3
Yar Hwee Boon wrote:

> I browsed for references of #removeSectionOrTag and didn't find any.

Hmm...

Did you also look for definitions of #removeSectionOrTag ?

    -- chris


Reply | Threaded
Open this post in threaded view
|

Re: #queryCommand: not called if a button's command changes

Yar Hwee Boon-3
On Fri, 9 Jul 2004 10:08:26 +0100, Chris Uppal  
<[hidden email]> wrote:

> Did you also look for definitions of #removeSectionOrTag ?
>
>     -- chris

Opps. There is 1 other definition in a presenter I am using. Basically the  
view/presenter structure is:

MyShell (defines MyShell>>removeSectionOrTag)
    MyPresenter (defines MyPresenter>>removeSectionOrTag)
    MyButton (command is #removeSectionOrTag)

So the button command is meant to be MyShell>>removeSectionOrTag which  
then delegates (calls) MyPresenter>>removeSectionOrTag. Seems that this  
name clash is causing the problem, because if I rename  
MyPresenter>>removeSectionOrTag to something else, MyShell>>queryCommand:  
is being sent for the button's command. Is it incorrect to have them share  
the same name? Seems unavoidable?

--
Regards
Hwee Boon
MotionObj


Reply | Threaded
Open this post in threaded view
|

Re: #queryCommand: not called if a button's command changes

Yar Hwee Boon-3
On Fri, 09 Jul 2004 18:16:52 +0800, Yar Hwee Boon <[hidden email]>  
wrote:

> Opps. There is 1 other definition in a presenter I am using. Basically  
> the view/presenter structure is:
>
> MyShell (defines MyShell>>removeSectionOrTag)
>     MyPresenter (defines MyPresenter>>removeSectionOrTag)
>     MyButton (command is #removeSectionOrTag)
>
> So the button command is meant to be MyShell>>removeSectionOrTag which  
> then delegates (calls) MyPresenter>>removeSectionOrTag. Seems that this  
> name clash is causing the problem, because if I rename  
> MyPresenter>>removeSectionOrTag to something else,  
> MyShell>>queryCommand: is being sent for the button's command. Is it  
> incorrect to have them share the same name? Seems unavoidable?

Just an update.. indeed, #queryCommand: is sent to both MyShell and  
MyPresenter for the commands of the buttons in MyShell, is that how it  
works? I had previously assumed that it should go to MyShell only. And  
because MyPresenter already defines #removeSectionOrTag, MyShell doesn't  
get the #queryCommand: call. Thanks.

--
Regards
Hwee Boon
MotionObj


Reply | Threaded
Open this post in threaded view
|

Re: #queryCommand: not called if a button's command changes

Chris Uppal-3
Yar Hwee Boon wrote:

> > MyShell (defines MyShell>>removeSectionOrTag)
> >     MyPresenter (defines MyPresenter>>removeSectionOrTag)
> >     MyButton (command is #removeSectionOrTag)
> >
[...]

> Just an update.. indeed, #queryCommand: is sent to both MyShell and
> MyPresenter for the commands of the buttons in MyShell, is that how it
> works?

It isn't supposed to.  Since the button is contained in MyShell, but not in
MyPresenter, I don't think that MyPresenter should be involved at all.  I've
tried a couple of ways to reproduce this, but my tests just behave the way I
expect them to.

I /suspect/ that you've done something (by accident, perhaps) that has changed
the command routing so that MyPresenter is on the command route when it
normally wouldn't be.

It's not easy to debug command handling, and is (I find) always rather
confusing.  The place I'd start is (as I said in the other post) putting a
breakpoint in #removeSectionOrTag.  After you've done that, you can invoke the
command, and then in the debugger restart the operation way back down the stack
at PushButton>>onActionPerformed, which will allow you to step through the
whole command routing sequence.  The first thing to look at is to see if the
CommandPolicy has the 'source' and 'path' that you'd expect.

    -- chris


Reply | Threaded
Open this post in threaded view
|

Re: #queryCommand: not called if a button's command changes

Yar Hwee Boon-3
On Sat, 10 Jul 2004 10:49:48 +0100, Chris Uppal  
<[hidden email]> wrote:

> I've
> tried a couple of ways to reproduce this, but my tests just behave the  
> way I
> expect them to.

Thanks, I appreciate that very much.

> I /suspect/ that you've done something (by accident, perhaps) that has  
> changed
> the command routing so that MyPresenter is on the command route when it
> normally wouldn't be.

Definitely not intentional :)

> confusing.  The place I'd start is (as I said in the other post) putting  
> a
> breakpoint in #removeSectionOrTag.  After you've done that, you can

#removeSectionOrTag wasn't sent to MyPresenter either.. clicking the  
button doesn't trigger anything, in fact I placed a self halt in  
PushButton>>actionPerformed and it was not called when I click the button.

> whole command routing sequence.  The first thing to look at is to see if  
> the
> CommandPolicy has the 'source' and 'path' that you'd expect.

I traced into ShellView>>commandSource. but didn't really get far enough  
with that, since the debugger window popping up is not helping with the  
isForeground check, and I was falling back to printing to the Transcript.  
But I did notice that it seems to be MyPresenter that is causing a  
problem, because if I replace it with another presenter that defines  
#removeSectionOrTag, everything works as expected. Any idea what I *could*  
have done wrong in that presenter?

--
Regards
Hwee Boon
MotionObj


Reply | Threaded
Open this post in threaded view
|

Re: #queryCommand: not called if a button's command changes

Bill Schwab-2
Hwee Boon,

> #removeSectionOrTag wasn't sent to MyPresenter either.. clicking the
> button doesn't trigger anything, in fact I placed a self halt in
> PushButton>>actionPerformed and it was not called when I click the button.

Are you certain that MyPresenter is being properly created and connected in
the MVP triad?  Something as simple as an incorrect name can cause very
confusing problems.  IIRC, the MVP framework is trying to be cooperative by
allowing one presenter to drive many different views, but it occaisionally
fails silently, which is either a bug or a feature depending on the
situation.  It might be nice to have an optional (probably on by default)
#subPresentersCanBeAbsent or something that one can override to force the
framework to generarate an error any time something isn't right between a
presenter and its view.

Have a good one,

Bill

--
Wilhelm K. Schwab, Ph.D.
[hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: #queryCommand: not called if a button's command changes

Yar Hwee Boon-3
On Sun, 11 Jul 2004 11:38:37 -0400, Bill Schwab  
<[hidden email]> wrote:

> Are you certain that MyPresenter is being properly created and connected  
> in
> the MVP triad?  Something as simple as an incorrect name can cause very
> confusing problems.  IIRC, the MVP framework is trying to be cooperative

Not that I can tell, of course it might have been obvious to someone  
else.. but I have been staring at this for days :) The good news is, I  
believe I can finally reproduce it. Can you, or Chris (Uppal) or anyone  
else help to verify by loading the package at  
http://motionobj.com/temp/HBRoutingReproduced.pac and running the  
following? Accordingly to MyShell>>queryCommand: both buttons should be  
disabled, but the #removeSectionOrTag button is active at my side.

        MyShell show.

Hopefully its not something stupid that I'm doing. Thanks.


--
Regards
Hwee Boon
MotionObj


Reply | Threaded
Open this post in threaded view
|

Re: #queryCommand: not called if a button's command changes

Chris Uppal-3
Yar Hwee Boon wrote:

> The good news is, I
> believe I can finally reproduce it. Can you, or Chris (Uppal) or anyone
> else help to verify by loading the package at
> http://motionobj.com/temp/HBRoutingReproduced.pac and running the
> following? Accordingly to MyShell>>queryCommand: both buttons should be
> disabled, but the #removeSectionOrTag button is active at my side.

I've given that a quick look.  I can confirm that the same problem is happening
on my machine too.

Have you noticed that if you press the 'Remove' button, it gets disabled
(possibly sounding a beep ? -- I can't tell on my machine since I don't allow
it to make any sounds), and will stay disabled until you shift the focus away
and back again.  That's what happens to me anyway.

I currently suspect that its a bug in the MVP framework for how Buttons are
enabled/disabled in idle-time processing.  The effect is that command route
that the button uses when you press it is not the same as the one used to
update the display in idle-time.  I haven't worked out the details, and I could
certainly be all wrong, but I think that the button includes the 'lastFocus'
when it is doing an idle-time refresh (from #validateUserInterface), but not
when it has actually been pressed.

In this case (for reasons I haven't looked at yet) the MyPresenter is the
lastFocus, so the buttons include it on their idle-time validation.  That makes
the 'Remove' button be enabled because MyPresenter does understand
#removeSectionOrTag (and has no #queryCommand: of its own, so the default check
is used).  But if you actually press the button, then the command is routed
using the normal route starting at the button and going out to the Shell
without ever touching the MyPresenter.

That's what it looks like to me just now, but I'm sure I must be missing
something or else this kind of problem would show up all over.  And it doesn't.

More later (probably), but it's time for me to start cooking my dinner...

    -- chris


Reply | Threaded
Open this post in threaded view
|

Re: #queryCommand: not called if a button's command changes

Bill Schwab-2
Chris,

> I currently suspect that its a bug in the MVP framework for how Buttons
are
> enabled/disabled in idle-time processing.  The effect is that command
route
> that the button uses when you press it is not the same as the one used to
> update the display in idle-time.  I haven't worked out the details, and I
could
> certainly be all wrong, but I think that the button includes the
'lastFocus'
> when it is doing an idle-time refresh (from #validateUserInterface), but
not
> when it has actually been pressed.

If nothing else, it's an interesting idea.  It might explain an intermittent
problem in one of my apps that runs on pen tablets (where the mouse cursor
can very erratic).  The problem is that buttons that should be enabled are
sometimes disabled until the user clicks somewhere on the dialog box in
question.  AFAIK, I've never seen the problem on desktop machines.

Have a good one,

Bill

--
Wilhelm K. Schwab, Ph.D.
[hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: #queryCommand: not called if a button's command changes

Yar Hwee Boon-3
In reply to this post by Chris Uppal-3
On Sun, 11 Jul 2004 20:47:39 +0100, Chris Uppal  
<[hidden email]> wrote:

> Have you noticed that if you press the 'Remove' button, it gets disabled
> (possibly sounding a beep ? -- I can't tell on my machine since I don't

No, it doesn't beep. PushButton>>actionPerformed is not called. The button  
then becomes disabled (I believe) due to another #validateUserInterface  
call, which with a change of focus (onto the button itself), causes  
MyShell>>queryCommand: to be called correctly, which disables the button.

> In this case (for reasons I haven't looked at yet) the MyPresenter is the
> lastFocus, so the buttons include it on their idle-time validation.  
> That makes
> the 'Remove' button be enabled because MyPresenter does understand
> #removeSectionOrTag (and has no #queryCommand: of its own, so the  
> default check

Same observation, I override MyPresenter>>#queryCommand: to confirm  
earlier.

> is used).  But if you actually press the button, then the command is  
> routed
> using the normal route starting at the button and going out to the Shell
> without ever touching the MyPresenter.

Probably not though, as PushButton>>actionPerformed: wasn't called.

>
> That's what it looks like to me just now, but I'm sure I must be missing
> something or else this kind of problem would show up all over.  And it  
> doesn't.

It does look like it should work, right? :)

--
Regards
Hwee Boon
MotionObj


Reply | Threaded
Open this post in threaded view
|

Re: #queryCommand: not called if a button's command changes

Chris Uppal-3
Yar Hwee Boon wrote:

> The button
> then becomes disabled (I believe) due to another #validateUserInterface
> call, which with a change of focus (onto the button itself), causes
> MyShell>>queryCommand: to be called correctly, which disables the button.

Good point.


> > That's what it looks like to me just now, but I'm sure I must be missing
> > something or else this kind of problem would show up all over.  And it
> > doesn't.
>
> It does look like it should work, right? :)

I haven't had a chance to investigate this any more, but it has occurred to me
that a natural way to express what (I think) you are trying to do, which
shouldn't suffer from this problem (or bug, if it is a bug) is for you to add
the MyPresenter to the MyShell command routing explicitly.  Then you could
remove the forwarding commands in the MyShell as well as the stuff in
MyShell>>queryCommand:

For instance, in MyShell, define:

    commandPolicyWithSource: sourceView
         ^ (super commandPolicyWithSource: sourceView)
              prependTarget: (self presenterNamed: 'tree');
              yourself.

Which seems to work for me in your example, but may not really be what you are
wanting to do.

    -- chris


Reply | Threaded
Open this post in threaded view
|

Re: #queryCommand: not called if a button's command changes

Yar Hwee Boon-3
On Mon, 12 Jul 2004 10:54:57 +0100, Chris Uppal  
<[hidden email]> wrote:

> Which seems to work for me in your example, but may not really be what  
> you are
> wanting to do.

I think you have misunderstood me. What I would like to do is actually  
very simple. Refer to the layout and code below. When the user clicks  
Button1, I would like it to invoke MyShell>>removeSectionOrTag, that's all.

MyPresenter>>removeSectionOrTag just *happens* to be there and has the  
same name (but of course what MyShell>>removeSectionOrTag does is to  
delegate to MyPresenter>>removeSectionOrTag). Did I misunderstood how the  
command should be routed? I *assumed* that a lookup for  
#removeSectionOrTag will done from the parent of Button1 (which is  
MyShell, therefore not involving MyPresenter) and move upwards. Does  
anyone has any docs or writeup on how this works, in case I've  
misunderstood? Thanks.

MyShell
     MyPresenter
     Button1


MyShell>>removeSectionOrTag
        "do something".
        myPresenter removeSectionOrTag.
        "do something".


--
Regards
Hwee Boon
MotionObj


Reply | Threaded
Open this post in threaded view
|

Re: #queryCommand: not called if a button's command changes

Chris Uppal-3
Yar Hwee Boon wrote:

> > Which seems to work for me in your example, but may not really be what
> > you are
> > wanting to do.
>
> I think you have misunderstood me. What I would like to do is actually
> very simple. Refer to the layout and code below. When the user clicks
> Button1, I would like it to invoke MyShell>>removeSectionOrTag, that's
> all.

No, adding the MyPresenter to the command route won't do that.  I had thought
that what you were really trying to do was to invoke the MyPresenter's
#removeSectionOrTag from a button that is in the containing MyShell, and that
the /only/ reason you were putting another #removeSectionOrTag in the main
Shell was in order to forward to the sub-presenter (and similarly for the code
in #queryCommand:).  If that's wrong then we can forget about changing the
command routing.


> MyPresenter>>removeSectionOrTag just *happens* to be there and has the
> same name (but of course what MyShell>>removeSectionOrTag does is to
> delegate to MyPresenter>>removeSectionOrTag). Did I misunderstood how the
> command should be routed? I *assumed* that a lookup for
> #removeSectionOrTag will done from the parent of Button1 (which is
> MyShell, therefore not involving MyPresenter) and move upwards.

That's my understanding too.  FWIW.


> Does
> anyone has any docs or writeup on how this works, in case I've
> misunderstood? Thanks.

The only documentation that /I/ know of is the code and comments -- especially
some of the class comments.  It has been discussed here a few times too; you
may be able to find something if you look for "chain of command" or "c-of-c"
pattern.

(BTW, I'd like to continue investigating this -- it's stretching my
understanding of command routing -- but I'm going to be busy arguing with
bureaucrats for the next day or so.  If I don't end up hanging myself, then
I'll be back later)

    -- chris


Reply | Threaded
Open this post in threaded view
|

Re: #queryCommand: not called if a button's command changes

Yar Hwee Boon-3
On Mon, 12 Jul 2004 19:53:26 +0100, Chris Uppal  
<[hidden email]> wrote:

> No, adding the MyPresenter to the command route won't do that.  I had  
> thought
> that what you were really trying to do was to invoke the MyPresenter's
> #removeSectionOrTag from a button that is in the containing MyShell, and  
> that
> the /only/ reason you were putting another #removeSectionOrTag in the  
> main
> Shell was in order to forward to the sub-presenter (and similarly for  
> the code
> in #queryCommand:).  If that's wrong then we can forget about changing  
> the
> command routing.

Besides forwarding to the sub-presenter, I also set a isModified flag in  
MyShell>>removeSectionOrTag, as I am implementing MyShell with  
DocumentShell-like behavior (for saving, cancelling changes). So I can't  
change the command routing as you suggested.

>
> (BTW, I'd like to continue investigating this -- it's stretching my
> understanding of command routing -- but I'm going to be busy arguing with
> bureaucrats for the next day or so.  If I don't end up hanging myself,  
> then
> I'll be back later)

Good luck and thanks. I'll be continuing my experiments too, will report  
back if I find anything.

ps: I am seeing this behavior in toolbars too :)


--
Regards
Hwee Boon
MotionObj


12