[comp.sys.next] How do I interrupt my App?

sisk@libra.cs.nps.navy.mil (Tamara Sisk) (11/05/90)

I'm polishing up a nifty App to submit to the sites, but I'm stuck on
one thing.

Part of the App involves creating a (very) long list in a ScrollView.
I want to be able to stop the listing without crashing my App, once
I'm happy with how long the list is.  Currently, there is a "Start" button
that starts the listing.  I'd like to make it so that this button
turns into a "Stop" button while the list is going, so that if
I push it again, the method creating the list just stops, just like
ScorePlayer, for example, whose start button turns into a stop button.

The problem seems to be that my App won't respond to button pushes
while the list-making method is working.  I've tried messing around
with [myButton setState:state] and things like this, but nothing
in my App responds until this one method finishes.

Surely someone out there can suggest how I get a Start/Stop toggle
button that actually works...


Oh, and by the way,  how will I go about submitting this to the ftp
sites once I fix this "last bug?"



-- 
_____________________________________________________________________
Jeff & Tamara Adams                           (or at least one of us)

dennisg@kgw2.bwi.WEC.COM (Dennis Glatting) (11/05/90)

In article <1614@libra.cs.nps.navy.mil>, sisk@libra.cs.nps.navy.mil (Tamara Sisk) writes:
|> I'm polishing up a nifty App to submit to the sites, but I'm stuck on
|> one thing.
|> 
|> Part of the App involves creating a (very) long list in a ScrollView.
|> I want to be able to stop the listing without crashing my App, once
|> I'm happy with how long the list is.  Currently, there is a "Start" button
|> that starts the listing.  I'd like to make it so that this button
|> turns into a "Stop" button while the list is going, so that if
|> I push it again, the method creating the list just stops, just like
|> ScorePlayer, for example, whose start button turns into a stop button.
|> 
|> The problem seems to be that my App won't respond to button pushes
|> while the list-making method is working.  I've tried messing around
|> with [myButton setState:state] and things like this, but nothing
|> in my App responds until this one method finishes.

try going multi-threaded.  this is your best solution.  have a thread build
a list while the other performs the normal App functions (button clicks,
event loop processing, /etc, /etc, /etc).

problem.  two threads cannot draw at the same time.  try disabling the display
of the list, build it, indicate such to the main thread either through a
speaker/listener or posting a user event.  then exit.  let the main thread
update the display.  also, when the main thread detects the "Stop" it could
terminate the builder thread.

in short.  no problem.  you just have to use your favorite cooperating
process mechanism.


--
 ..!uunet!kgw2!dennisg      | Dennis P. Glatting
 dennisg@kgw2.bwi.WEC.COM   | X2NeXT developer

glenn@heaven.woodside.ca.us (Glenn Reid) (11/06/90)

In article <1614@libra.cs.nps.navy.mil> sisk@cs.nps.navy.mil (Tamara Sisk) writes:
>I'm polishing up a nifty App to submit to the sites, but I'm stuck on
>one thing.
>
>Part of the App involves creating a (very) long list in a ScrollView.
>I want to be able to stop the listing without crashing my App, once
>I'm happy with how long the list is.  Currently, there is a "Start" button
>that starts the listing.  I'd like to make it so that this button
>turns into a "Stop" button while the list is going, so that if
>I push it again, the method creating the list just stops, just like
>ScorePlayer, for example, whose start button turns into a stop button.

This turns out to be a little more complicated than you might think,
but below is some code that does the trick, thanks to some pointers from
NeXT people a long time ago.

The basic idea is this:
	* start a "modal session" for the active window
	* enter your busy loop in which you create the long
	  list in the scrollview
	* periodically within the loop you call a method to see
	  if the modal dialog has been stopped, and exit the loop if so
	* end the modal session and clean up

Here are some code fragments; assume that you have a button that triggers
a method called "stop" in your object, and that the object itself has a
outlet to the button called "stopButton" so it can disable it.  My code
does not make the same button into the STOP button, but you can figure
out that part.


/****************************** yourMethod */
- yourMethod:sender
{
    NXModalSession session;
    short whatever = TRUE;

    [NXApp beginModalSession: &session for: window];
    [stopButton setEnabled:TRUE];
    while ( whatever ) {
	if ( [NXApp runModalSession: &session] != NX_RUNCONTINUES ) {
	    // stop button was hit
	    // clean up and exit while loop
	    break;
	}
    }
    [NXApp endModalSession: &session];
    [stopButton setEnabled:FALSE];
    return self;

} // yourMethod


/****************************** stop */
- stop:sender
{

    [NXApp stopModal];
    NXBeep();
    NXRunAlertPanel ( "Stopped",
	"Stopped at your request.", NULL, NULL, NULL
    );
    return self;
    
} // stop


-- 
 Glenn Reid				RightBrain Software
 glenn@heaven.woodside.ca.us		PostScript/NeXT developers
 ..{adobe,next}!heaven!glenn		415-851-1785

wisdom@pico.cs.umn.edu (Scott Wisdom) (11/06/90)

In article <1614@libra.cs.nps.navy.mil> you write:
>The problem seems to be that my App won't respond to button pushes
>while the list-making method is working.  I've tried messing around
>with [myButton setState:state] and things like this, but nothing
>in my App responds until this one method finishes.
>
>Surely someone out there can suggest how I get a Start/Stop toggle
>button that actually works...

A single process is not multitasking by default in mach (or unix),
which means as long as it's busy doing something, nothing - not
even the event loop - will run. You could use multiple threads,
but that can get tricky. Your best bet is to use DPS timed entries.
Rewrite your list building method into a function that will perform
a few steps of the list building process each time it's called,
dropping out and returning control to the app when those few steps
are done. Now in your button action method, add a
DPSAddTimedEntry() call with your newly written function as the
targtet of the timed entries (Chapter 23 of the on-line docs
discusses DPSAddTimedEntry(), and a great example is located in /NextDeveloper/Examples/Clock in the file AnalogClock.m). You can
also add code to change the title of the button (something like
[myButton setTitle:"STOP!"]). Once your button is pressed, it will
start the timed entry and return control to the event loop.
DPSAddTimedEntry will cause the repeated execution of that
function via events in the event loop, and allow other events to
be posted, such as the button being pressed again to stop the
process.

-Scott Wisdom
wisdom@heckle.cs.umn.edu
Coda Music Software Hacker

sstreep@next.com (Sam Streeper) (11/07/90)

In article <1614@libra.cs.nps.navy.mil> you write:
>I'm polishing up a nifty App to submit to the sites, but I'm stuck on
>one thing.
>
>Part of the App involves creating a (very) long list in a ScrollView.
>I want to be able to stop the listing without crashing my App, once
>I'm happy with how long the list is.  Currently, there is a "Start" button
>that starts the listing.  I'd like to make it so that this button
>turns into a "Stop" button while the list is going, so that if
>I push it again, the method creating the list just stops, just like
>ScorePlayer, for example, whose start button turns into a stop button.
>

Just in case no one else responds:
Button objects recieve mouse down events from the event loop.  If you
run your code but never return to the event loop until you're done
with your scroll method, no message will be sent to the button, so
the button can't invoke its action method, which would presumably set
a stop flag.  I can think of 3 things you might do:

1) Have a 'scroll one step' method repeatedly invoked by a timed entry.
See BreakApp in the developer demos for an example of a timed entry
function.

2) Put the scrolling in a modal responder loop:
    NXModalSession session;
    [NXApp beginModalSession:&session for:theWindow];
    for (;;) {
        if ([NXApp runModalSession:&session] != NX_RUNCONTINUES)
            break;
    /* scroll one line here... */
    }
    [NXApp endModalSession:&session];
Then your button action method will send a 'stopModal' message.  This is
probably the easiest way to do what you want.

3) You might do this by peeking at the next event,
either using the Application class methods or DPS functions.  This
certainly is not the best way to do this so I won't dig up an example.

I hope I understood your question and answered it adequately.

>_____________________________________________________________________
>Jeff & Tamara Adams                           (or at least one of us)

-sam

Opinions expressed here are my own.  You can borrow them for a dollar.

wiml@milton.u.washington.edu (William Lewis) (11/07/90)

In article <1614@libra.cs.nps.navy.mil> sisk@cs.nps.navy.mil (Tamara Sisk) writes:
>I'm polishing up a nifty App to submit to the sites, but I'm stuck on
>one thing.
>
>The problem seems to be that my App won't respond to button pushes
>while the list-making method is working.  I've tried messing around
>with [myButton setState:state] and things like this, but nothing
>in my App responds until this one method finishes.

   That's because while you're doing your processing, the event loop is
basically stoped (waiting for your methodto return), not processing
mouse events or redrawing the windows. If you don't want to go the route
of multiple threads (as suggested by another poster), you could try
a modal loop. The Application class has a bunch of methods for things like
this. What you want is (if I remember correctly) startModalSessionFor:.
There are four or so methods that do this that operate on (NXSession *)s.
The stated purpose is so that the app can do timeconsuming things but
still allow the user to stop them via button presses. (Sounds familiar,
no?) You basically poll the event queue periodically by calling these 
methods, and NXApp will call your button's target if necessary, so it
can set a flag (or maybe there's a way to make the polling method
return maningful values). 


>Oh, and by the way,  how will I go about submitting this to the ftp
>sites once I fix this "last bug?"

   Last I checked, you can:

   (1) upload to the submissions directory if it's writeable
   (2) send mail to the site's keeper so they notice, I guess you'd
        include the app uuencoded if you couldn't do (1)


  Hope to see your application in the archives soon! =8)

-- 
 wiml@milton.acs.washington.edu       Seattle, Washington   
     (William Lewis)   |  47 41' 15" N   122 42' 58" W  
"These 2 cents will cost the net thousands upon thousands of 
dollars to send everywhere. Are you sure you want to do this?"