Dialog events

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

Dialog events

Osvaldo Aufiero-2
In need to do something (set focus on a TextEdit) but I tried doing this in
#onViewOpened. It doesn't do anything, because the view hasn't the focus.
Could somebody explain to me when is the view shown ? Does it triggers an
event?

TIA

Osvaldo


Reply | Threaded
Open this post in threaded view
|

Re: Dialog events

Bill Dargel
Osvaldo Aufiero wrote:
> In need to do something (set focus on a TextEdit) but I tried doing this in
> #onViewOpened. It doesn't do anything, because the view hasn't the focus.
> Could somebody explain to me when is the view shown ? Does it triggers an
> event?

Hopefully, someone here can give you the "right" answer. I just wanted
to point out the hack that can sometimes be useful to bail out of
situations. In your case something like:
    [aPresenter setFocus] postToInputQueue.
might give you what you need.

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


Reply | Threaded
Open this post in threaded view
|

Re: Dialog events

Osvaldo Aufiero-2
it works great!
tks Bill!

"Bill Dargel" <[hidden email]> wrote in message
news:[hidden email]...
> Osvaldo Aufiero wrote:
> > In need to do something (set focus on a TextEdit) but I tried doing this
in
> > #onViewOpened. It doesn't do anything, because the view hasn't the
focus.
> > Could somebody explain to me when is the view shown ? Does it triggers
an

> > event?
>
> Hopefully, someone here can give you the "right" answer. I just wanted
> to point out the hack that can sometimes be useful to bail out of
> situations. In your case something like:
>     [aPresenter setFocus] postToInputQueue.
> might give you what you need.
>
> -------------------------------------------
> Bill Dargel            [hidden email]
> Shoshana Technologies
> 100 West Joy Road, Ann Arbor, MI 48105  USA


Reply | Threaded
Open this post in threaded view
|

Re: Dialog events

Ian Bartholomew-18
In reply to this post by Osvaldo Aufiero-2
Osvaldo,

> In need to do something (set focus on a TextEdit) but I tried doing
> this in #onViewOpened. It doesn't do anything, because the view
> hasn't the focus. Could somebody explain to me when is the view shown
> ? Does it triggers an event?

If I'm reading this right you want a Dialog to open with the focus
within the new Dialog set to a TextEdit subview?  If so then the easiest
way is to rearrange the order of the views (using the ViewComposer) so
that the TextEdit is the first subview in the View Hierarchy tree-
Dolphin sets the initial focus on the first subview that is a tab stop.

Another way of doing it would to be to defer the #setFocus until Windows
has fully displayed the Dialog ....

onViewOpened
    super onViewOpened.
    [yourTextEdit setFocus] postToInputQueue

--
Ian

Use the Reply-To address to contact me.
Mail sent to the From address is ignored.


Reply | Threaded
Open this post in threaded view
|

Re: Dialog events

Bill Schwab-2
Ian,

> Another way of doing it would to be to defer the #setFocus until Windows
> has fully displayed the Dialog ....
>
> onViewOpened
>     super onViewOpened.
>     [yourTextEdit setFocus] postToInputQueue

FWIW, I'm starting to think that this should be last resort because it makes
the code unfriendly to unit tests.  However, I suspect that it is more
necessary in dialogs than other presenters.  I also don't like to be forced
to break up every dialog into a regular presenter that I can unit test, only
to wrap it in a trivial dialog simply to obtain modal operation.  Sometimes
such a split helps reuse, which is of course the right thing to do.  Other
times, it walks, talks, and sounds like a workaround, and makes the code
much harder to understand.

To the the group at large: has anyone created a non-dialog modal presenter?
I think it might help.  One of my older manuals (IIRC, WindowBuilder's)
makes a good case for having control over the message loop, and the more I
write unit tests for GUI elements, the more I want to give it a try.

Have a good one,

Bill

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


Reply | Threaded
Open this post in threaded view
|

Re: Dialog events

Bill Dargel
Ian and I had suggested:
>      [yourTextEdit setFocus] postToInputQueue
 
Bill Schwab wrote:
> FWIW, I'm starting to think that this should be last resort because it makes
> the code unfriendly to unit tests.  However, I suspect that it is more
> necessary in dialogs than other presenters.  I also don't like to be forced
> to break up every dialog into a regular presenter that I can unit test, only
> to wrap it in a trivial dialog simply to obtain modal operation.  

It probably _should_ be the last resort. But being Smalltalk, one can
usually do just about anything. So a while ago, I set aside any
semblance of good sense, showed no fear, and hacked together a couple of
methods that do help to make modal dialogs and unit tests a bit more
harmonious. I've attached them for everyone's amusement.

A word of warning though, they're not pretty to look at, and could
easily trigger a gag reflex.

The #waitForUIProcessToIdle method, when called from a TestCase, allows
any pending UI messages and defferedActions to complete. With this, a
testCase can check for expected state in its scripted mode and get
(closer at least to) what the user would be seeing in the normal
interactive mode. It works by just forking off a low priority process
and then blocking the execution of the testCase (keeping the UI pumping)
until the low priority process has gotten an opportunity to run.

The rather more involved #should:openModalShell:answer: method can be
utilized by TestCases where doing some GUI operation is expected to open
a model dialog. For instance, you can use it to test that pressing a
button opens a Prompter, and then check that the caption, prompt, etc.,
are as expected. You can also go on further to set values into the
dialog and then give it an #ok or #cancel, and check afterwards that the
main window has responded appropriately.

An example of using it within a testCase might be:
    self
        should: [(self viewNamed: 'addCopy') performAction]
        openModalShell:
            [:topShell |
            self assert: topShell class = DatePrompter.
            self assert: topShell caption = 'Select new effective start
date:'.
            self assert: topShell value = Date today firstOfWeek.
            topShell value: '7/7/03' asDate]
        answer: #ok.
    self assert: model startDate = '7/7/03' asDate.

I'd be interested to see if anyone else has done something similar? The
methods have been working for me as they stand. But I'm sure there must
be cases that I haven't run into where they'll break down. So if there's
a more robust way, that would be great.

-Bill

-------------------------
!InputState methodsFor!

waitForUIProcessToIdle
        "General hack to simulate the idling of the system so that testCases
         can proceed once everything in the UI process has been taken care of."

        | uiWorking semaphore |
        uiWorking := true.
        semaphore := Semaphore new.
       
        [uiWorking := false.
        semaphore signal.
        SessionManager inputState prod]
                        forkAt: Processor userBackgroundPriority.
        Processor isActiveMain
                ifTrue: [SessionManager inputState loopWhile: [uiWorking]]
                ifFalse: [semaphore wait]! !


!TestCase methodsFor!

should: activationBlock openModalShell: verificationBlock answer:
aSymbol
        | activationProcess previousTopShell topShell semaphore activationError
|
        semaphore := Semaphore new.
        previousTopShell := View active presenter.

        "Flush any UI events so that another window won't become the top view
after we cause the dialog to open."
        SessionManager inputState waitForUIProcessToIdle.

        "Evaluate the <activationBlock> which should popup a modal dialog.
        Grab any errors in the forked process to later resignal in this
process."
        activationProcess :=
                        [[[activationBlock value] on: Error do: [:ex | activationError := ex
copy]]
                                ensure: [semaphore signal]]
                                        forkAt: Processor userHigherPriority.

        "Set a timeout just in case the activation block never completes"
       
        [Processor sleep: 2000.
        activationProcess terminate] fork.
       
        [SessionManager inputState waitForUIProcessToIdle.
        "Verify that the dialog opened"
        topShell := View active presenter.
        self assert: topShell ~= previousTopShell.
        "Perform any user validation"
        verificationBlock value: topShell.
        "Execute the dialog answer, such as #yourself, #ok or #cancel"
        topShell perform: aSymbol.
        SessionManager inputState processDeferredActions]
                        ensure:
                                [topShell view close.
                                "Closing the dialog signals the waiting window via a deferredAction,
                                which will cause the button's performAction to finally complete"
                                SessionManager inputState waitForUIProcessToIdle.
                                "Wait for that to happen so that nesting of Cursors won't get messed
up"
                                semaphore wait].
        activationError notNil ifTrue: [activationError signal]! !

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


Reply | Threaded
Open this post in threaded view
|

Re: Dialog events

Blair McGlashan-2
In reply to this post by Osvaldo Aufiero-2
"Osvaldo Aufiero" <[hidden email]> wrote in message
news:[hidden email]...
> In need to do something (set focus on a TextEdit) but I tried doing this
in
> #onViewOpened. It doesn't do anything, because the view hasn't the focus.
> Could somebody explain to me when is the view shown ? Does it triggers an
> event?

To explicitly set the initial focus in a dialog (or any other shell) you
should override #setInitialFocus. However the default behaviour of setting
focus to the first child control with #isTabStop = true is normally
appropriate, so there should be no need to define #setInitialFocus in most
cases.

Regards

Blair