Re: Prevent Asynchronous operation of beginSheetModalForWindow

2008-06-28 Thread John Love
 (1) warning: no doSheetSelection:contextInfo method found which, I think,
 is
 due to the fact that the external class of mFileSheetDelegate =
 FileController, yet when referenced in SaveSheetController, it's = id, a
 general pointer.  But, I thought all anonymous pointers were resolved at
 runtime ... am I just going to force myself to ignore this Build Warning,
 knowing that it will all go away at runtime???



 The reason for this is because the sheet controller is not aware of your
 File Controller's methods. Nor should it be. So how to resolve it? The
 answer is to declare the callback method as an informal protocol *within
 SheetController.h* Thus:

 I figured this out while I was mowing the lawn yesterday (before reading
this reply) (really!) -- do not have a clue what sort of Freudian psychology
this demonstrates -- cutting off the heads of delegates and informal
protocols, maybe?  Regardless of the deviant psychology, I remember thinking
(while pushing the mower) so that's what informal protocols are good for ..
delaying the presentation of Build Errors until runtime when all unresolved
references are - duh - resolved!!!



  (2)I still get unrecognized selector .. but,


 That's because you're targeting the wrong object. Here:


no psychology here, just plain brain-dead on my part



 You have got to get these relationships straight in your mind. It's not
 that hard. I've goaded and prompted you and written your code for you piece
 by piece - that's great, it solves your problem. But has it increased your
 understanding? I fear it hasn't, and it still all seems like voodoo. I'm not
 sure what I can do about that.


Amen to that .. no excuses here .. trying to do too many things at once ..
get re-acquainted with C, trying to use the same logic as my application's
AppleScript Studio Project counterpart .. Cocoa delegates .. who does what
to whom behind the scenes.

Anyway, it finally sunk in to keep all UI objects(buttons) local to the
individual sheet controllers and have the file controller worry only about
return codes.  I also figured out (quirky psychology as noted above)
informal protocols .. my file controller imports WhateverSheetController.h
and to do away with informal protocols would necessitate
WhateverSheetController.h to import FileController.h, aka a perfect
circle, aka failure to compile.

BTW, the reason for my originally passing (NSWindow*)sheet to
doSheetSelection within FileController.m was so this method could call
[sheet closeOut:self] .. not required now that I call the latter within the
sheet's didEndSelector.

I'll guarantee you one thing .. no one could ask for a more patient teacher
that you .. trust me, I mean that, every syllable. You remind me of an old
Physics prof I had many, many, many years ago who made physics sound so darn
simple (once it sunk in, which it did with minimal effort since I was so
young at the time).

Anyway, got some more things to understand (Menus and Toolbars) and probably
more questions to ask later, so ...

John
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Prevent Asynchronous operation of beginSheetModalForWindow

2008-06-27 Thread John Love
Graham,

Yup, Nathan the double indirection of id *

1st, just the key snippet from FileController.m:

@implementation FileController

id mFileSheetDelegate;

=

Here's the complete interface and implementation files for just one
SheetController, which has 2 buttons in its sheet window:

// SaveSheetController.h

#import Cocoa/Cocoa.h

@interface SaveSheetController:NSWindowController {
IBOutlet NSTextField *iboSaveDescription;
}
- (void) showSheetOnParentWindow:(NSWindow*)parentWindow
 withDescription:(NSString*)theDescription
 delegate:(id)theTarget
 contextInfo:(void*)contextInfo;
- (void) sheetDidEnd:(NSWindow*)sheet
 returnCode:(int)returnCode
 contextInfo:(void*)contextInfo;
- (IBAction) saveIt:(id)sender;
- (IBAction) dontSaveIt:(id)sender;
- (void) closeSheet:(id)sender withCode:(int)theCode;
@end

===

// SaveSheetController.m

#import SaveSheetController.h

enum {
kJustSave,   /* 0, 1 */
kJustNotSave
};

@implementation SaveSheetController

extern id mFileSheetDelegate;

- (void) showSheetOnParentWindow:(NSWindow*)parentWindow
 withDescription:(NSString*)theDescription
 delegate:(id)theTarget
 contextInfo:(void*)contextInfo {
mFileSheetDelegate = theTarget;

if (theDescription) {
// do magic
}

[NSApp beginSheet:[self window]
  modalForWindow:parentWindow
  modalDelegate:theTarget
  didEndSelector:@selector
(sheetDidEnd:returnCode:contextInfo:)
  contextInfo:contextInfo];
}

// 2 buttons of saveSheet
- (IBAction) saveIt:(id)sender {
[self closeSheet:sender withCode:kJustSave];
}

- (IBAction) dontSaveIt:(id)sender {
[self closeSheet:sender withCode:kJustNotSave];
}

- (void) closeSheet:(id)sender withCode:(int)theCode {
NSWindow* theSheet;
theSheet = [sender window];

[NSApp endSheet:theSheet returnCode:theCode];   // calls didEndSelector
}

- (void) sheetDidEnd:(NSWindow*)sheet
 returnCode:(int)returnCode
 contextInfo:(void*)contextInfo {
[mFileSheetDelegate doSheetSelection:returnCode
contextInfo:contextInfo];

[sheet orderOut:self];
}

@end



Finally, a snippet or two from [doSheetSelection:contextInfo]:

- (void) doSheetSelection:(int)returnCode
  contextInfo:(void*)contextInfo {

/*
If we had different sheets returning the same code,
then we would select between the different sheet IDs.
But, for our case, all returned IDs are unique.

if ([(NSString*)contextInfo isEqualToString:sCalculateSheetID]) {
}
if ([(NSString*)contextInfo isEqualToString:sSaveSheetID]) {
}
if ([(NSString*)contextInfo isEqualToString:sErrorSheetID]) {
}
*/

switch (returnCode) {
case kJustSave:
[self saveSpreadsheet];

gShouldCloseDoc = TRUE;
break;

case kJustNotSave:
[self setStatus:sFileNotSavedMsg];

gShouldCloseDoc = TRUE;
break;
}



Okay ... all the snippets are done ... now, the questions:

(1) warning: no doSheetSelection:contextInfo method found which, I think, is
due to the fact that the external class of mFileSheetDelegate =
FileController, yet when referenced in SaveSheetController, it's = id, a
general pointer.  But, I thought all anonymous pointers were resolved at
runtime ... am I just going to force myself to ignore this Build Warning,
knowing that it will all go away at runtime???

(2)I still get unrecognized selector .. but,
didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:)
is within the sheet.m .. good grief!

John
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Prevent Asynchronous operation of beginSheetModalForWindow

2008-06-27 Thread Graham Cox


On 28 Jun 2008, at 12:38 am, John Love wrote:


[code snipped]


Finally, you nailed it, almost (one small bug, see below). Phew!





Okay ... all the snippets are done ... now, the questions:

(1) warning: no doSheetSelection:contextInfo method found which, I  
think, is

due to the fact that the external class of mFileSheetDelegate =
FileController, yet when referenced in SaveSheetController, it's =  
id, a
general pointer.  But, I thought all anonymous pointers were  
resolved at
runtime ... am I just going to force myself to ignore this Build  
Warning,

knowing that it will all go away at runtime???



The reason for this is because the sheet controller is not aware of  
your File Controller's methods. Nor should it be. So how to resolve  
it? The answer is to declare the callback method as an informal  
protocol *within SheetController.h* Thus:


@interface NSObject (SheetSelectionDelegate)

- (void) doSheetSelection:(int)returnCode contextInfo: 
(void*)contextInfo;


@end

Now, your sheet controller does know that there is a method that has  
this signature, so the warning will go away. But because the method is  
defined as a category of NSObject, you still have avoided exposing  
SheetController to the inner workings of your FileController. This is  
the more precise, and correct meaning of informal protocol, and  
generally you implement them as categories on NSObject.



(2)I still get unrecognized selector .. but,


That's because you're targeting the wrong object. Here:

   [NSApp beginSheet:[self window]
 modalForWindow:parentWindow
 modalDelegate:theTarget		// 
-- uh-oh

 didEndSelector:@selector
(sheetDidEnd:returnCode:contextInfo:)
 contextInfo:contextInfo];

You should be passing 'self', not 'theTarget' as  modalDelegate. Why?  
Because it is the sheet controller that is the modal delegate of the  
*sheet*, which is what this specifies. The target is the delegate of  
the sheet *controller*, so the sheet itself doesn't want this. You  
already dealt with that by recording the target in your own ivar.


You have got to get these relationships straight in your mind. It's  
not that hard. I've goaded and prompted you and written your code for  
you piece by piece - that's great, it solves your problem. But has it  
increased your understanding? I fear it hasn't, and it still all seems  
like voodoo. I'm not sure what I can do about that.


cheers, Graham


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Prevent Asynchronous operation of beginSheetModalForWindow

2008-06-26 Thread John Love
Graham,

Still pouring over your thesis .. in process, so let me ask just one thing
at a time, rather than chew here on the whole thing.

(1) learning about anonymous type = (id) .. I make this call within FC:

[iboCalculateSheetCtrl showSheetOnParentWindow:itsWindow
   withDescription:nil
   delegate:self
   contextInfo:sCalculateSheetID];

The delegate here is FileController*, where the delegate received within
SC's showSheetOnParentWindow looks like:

- (void) showSheetOnParentWindow:(NSWindow*)parentWindow
 withDescription:(NSString*)theDescription
 delegate:(id)theTarget
 contextInfo:(void*)contextInfo {

mFileSheetDelegate = theTarget;

// etc.

}

and at the very top:

@implementation CalculateSheetController

id *mFileSheetDelegate;

Within the implementation of showSheetOnParentWindow, I get assignment from
incompatible pointer type with:

mFileSheetDelegate = theTarget;

and later on within this SC's implementation:

- (void) sheetDidEnd:(NSWindow*)sheet
 returnCode:(int)returnCode
 contextInfo:(void*)contextInfo {
[mFileSheetDelegate doSheetSelection:sheet returnCode:returnCode
contextInfo:contextInfo];
}

I get: warning:invalid receiver type 'id' and

no matching doSheetSelection:returnCode:contextInfo.

Based on the invalid .. warning, I understand no matching ...

By the way my FC has the formal doSheetSelection:returnCode:contextInfo
selector or method .. one final thing on this item, I do not really
understand informal protocols, so I have not yet tried to implement such.

John
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Prevent Asynchronous operation of beginSheetModalForWindow

2008-06-26 Thread Nathan Kinsinger


On Jun 26, 2008, at 8:19 AM, John Love wrote:



@implementation CalculateSheetController

id *mFileSheetDelegate;


id is already typed as a pointer, no need to add another level of  
indirection here.


--Nathan
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Prevent Asynchronous operation of beginSheetModalForWindow

2008-06-26 Thread Graham Cox


On 27 Jun 2008, at 12:19 am, John Love wrote:


Still pouring over your thesis


I thought it was getting a bit damp around here... ;-)


and at the very top:

@implementation CalculateSheetController

id *mFileSheetDelegate;

Within the implementation of showSheetOnParentWindow, I get  
assignment from

incompatible pointer type with:



id already is a pointer, so you don't want the *



and later on within this SC's implementation:

- (void) sheetDidEnd:(NSWindow*)sheet
returnCode:(int)returnCode
contextInfo:(void*)contextInfo {
   [mFileSheetDelegate doSheetSelection:sheet returnCode:returnCode
contextInfo:contextInfo];



Looking much better, but one question: why are you passing sheet to  
your FC? Why on earth does it need it? Again this exposes UI  
implementation details to an unrelated controller that shouldn't need  
to care about that.


By the way my FC has the formal  
doSheetSelection:returnCode:contextInfo

selector or method .. one final thing on this item, I do not really
understand informal protocols, so I have not yet tried to  
implement such.


Well, you could try searching the docs for that phrase...

But in simple terms an informal protocol is just a method or methods  
that different objects agree between themselves will be how they  
communicate (and by 'agree between themselves' I mean that you, the  
programmer, made that decision). In fact you are using them all the  
time whenever you write any method that another object calls. Don't be  
too misled by the jargon, there's not much more to it than that. A  
*formal* protocol on the other hand, is much stricter, and uses the  
@protocol directive, but I won't get into that, you probably don't  
need to know. The term 'informal' is really there to distinguish it  
from a formal @protocol situation.


cheers, Graham
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Prevent Asynchronous operation of beginSheetModalForWindow

2008-06-19 Thread John Love
Completed the housekeeping I needed to do .. so I began moving all the sheet
code over to SheetController.

Within FileController, I have 3 IBOutlets which are the 3 different sheet
NSWindow's *and* the same 3 sheet NSWindow outlets for SheetController.  I
need to pass the specific sheet to my showSheet method within FileController
and the showSheet method within SheetController needs to differentiate
between the 3 different ones in order to place the withDescription
NSString in the appropriate NSTextField of each sheet.

All buttons for each sheet are connected to various IBAction's in
FileController.

The resulting calls from FileController to SheetController look like this:

[theSheet showSheet:saveSheet forWindow:itsWindow
withDescription:nil onCompletion:nil]; *and*

**
please note that for now, I always pass nil for the completion selector
because I haven't *yet* figured out what to do within that selector
(probably just a long switch statement based on enumerated constants - I did
*not* know that Objective C is based on C, not C++ - I got case identifier
needs constant integer, so placed constants inside an enum).

Anyway, I keep getting unrecognized selector sent to instance ... (see
footprint at the very bottom of this message).

In the meantime, I call within FileController:

shouldClose = ([theSheet getReturnCode] == doCloseDoc);  // should I
close the mainWindow or not?

once I get a handle on that unrecognized selector error, I can get rid of
any calls from FileController to SheetController's getReturnCode.
**

an example of an IBAction method within FileController (that is connected
within IB to one of the sheet buttons):
- (IBAction) keeponCalculating:(id)sender {

[theSheet closeSheetWithCode:notCloseDoc]; // or, doCloseDoc, integers 0
or 1, depending on method

[self doSomethingHere];

}

The showSheet, getReturnCode and closeSheetWithCode methods within
SheetController looks like:

- (void) showSheet:(NSWindow*)whichSheet
   forWindow:(NSWindow*)theWindow
   withDescription:(NSString*)theDescription
   onCompletion:(SEL)doThis {

if (theDescription) {
if (whichSheet == calculateSheet) {
if (calculateDescription)  // if connected in IB
[calculateDescription setStringValue:theDescription];
}
else if (whichSheet == saveSheet) {
// etc
}
else if (whichSheet == errorSheet) {
// etc.
}

[NSApp beginSheet:whichSheet
  modalForWindow:theWindow
  modalDelegate:nil
// right now, I pass nil as doThis, but if I pass
@selector(sheetDidEnd:returnCode:contextInfo:)
// I get unrecognized selector sent to instance ...
  didEndSelector:doThis
  contextInfo:nil];
itsReturnCode = [NSApp runModalForWindow:whichSheet];

[NSApp endSheet:whichSheet];
[whichSheet orderOut:self];

}


/* -- doThis defined in FileController.m
- (void) sheetDidEnd:(NSWindow*)whichSheet
 returnCode:(int)returnCode
 contextInfo:(void*)contextInfo {
}
*/

- (int) getReturnCode {
return itsReturnCode;
}

- (void) closeSheetWithCode:(int)theCode {
[NSApp stopModalWithCode:theCode];
}
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Prevent Asynchronous operation of beginSheetModalForWindow

2008-06-17 Thread John Love
I have your previous message typed out and I really have read it ... and I
will re-read it and re-read until it clicks. You know how I feel about
compartmentalization.  I really don't want to abandon it because
compartmentalization does work for me for the NSProgressIndicator that I
have, as well as my Toolbar.

The only saving grace is that I've got sheets down to a science when I meld
my sheet code into FileController ... and you have no idea how happy that
makes me.  Right now, I'm cleaning up the code ... renaming outlets and some
instance variables so they sound like plain English.

When I am finished with this housekeeping, I fully intend to return to sheet
compartmentalization ... I have not given up ... I just wanted to get sheets
to work.

I will give you all the feedback when the elevator reaches the top.

With regards,

John Love
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Prevent Asynchronous operation of beginSheetModalForWindow

2008-06-16 Thread John Love
Hello, Graham ...

Because I have multiple calls to show a sheet, from various parts of my
FileController, and because I wanted to make my sheet calls as general as
possible, I really .. really .. wanted to have a distinct SheetController.
As a result, I made calls from FileController to look like:[theSheet
showSheet:itsWindow], where theSheet was an outlet of FileController.

I could get away with that since all my sheets had just one button .. except
one, which had 3 buttons .. and for that exception, the asynchronous nature
of sheets got in the away.

I have not given up on a separate SheetController .. however .. I finally
reduced my showSheet routine to something very, very short and placed it in
FileController ..

- (void) showSheet: (NSWindow*)theSheet
forWindow:(NSWindow*)theWindow
withDescription:(NSString*)theDescription {

if (theDescription) {
if (theSheet == calculateSheet) {
if (calculateDescription)  // NSTextField outlets of
FileController, 1 per sheet
[calculateDescription setStringValue:theDescription];
}
else if (theSheet == saveSheet) {
if (saveDescription)
[saveDescription setStringValue:theDescription];
}
else if (theSheet == errorSheet) {
if (saveDescription)
[saveDescription setStringValue:theDescription];
}
}

[NSApp beginSheet:theSheet
  modalForWindow:theWindow
  modalDelegate:nil
  didEndSelector:nil  //
@selector(sheetDidEnd:returnCode:contextInfo:)
  contextInfo:nil];
itsReturnCode = [NSApp runModalForWindow:theSheet]; // (int)
itsReturnCode in FileController.h

[NSApp endSheet:theSheet];
[theSheet orderOut:self];

}

When I called showSheet, it looked like:
 [self showSheet:calculateSheet forWindow:itsWindow
withDescription:nil]where calculateSheet, showSheet and errorSheet were 3
IBOutlets of FileController, all of class = NSWindow.

Every button of each sheet was connected to a specific IBAction of
FileController, e.g.,

- (IBAction) dontSaveIt:(id)sender {
   [self closeSheetWithCode:doCloseDoc];
}

with that last message looking like:

- (void) closeSheetWithCode:(int)theCode {

[NSApp stopModalWithCode:theCode];

}

As the docs explain, when you do that, the message [NSApp
runModalForWindow:] returns that identical integer, which can be any integer
of your choosing.  In my case, the integer choices trigger a decision
whether to close the mainWindow after the sheet is closed, or whether to
keep mainWindow open after the sheet is closed.

I did not even have to mess with sheetDidEnd selectors because
closeSheetWithCode returned gave the needed flag I could use to quantify the
itsReturnCode instance variable of FileController.

Anyway, I have sheets, not the relatively antequated separate dialogs.

I have no intention of giving up on a separate SheetController .. but, in
the meantime, I have something that works.

Best regards,

John Love
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Prevent Asynchronous operation of beginSheetModalForWindow

2008-06-16 Thread Graham Cox

Hi John,

Did you even read my last email? I hope so because I really spent a  
long time writing it. It may not have been clear, but I did my best!


A separate SheetController *is* the right way to do it, but the way  
you are partitioning the responsibilities between your various  
controllers isn't right. Your FileController should not be caring one  
iota about how the SheetController works, or gets its information. If  
it's asking the sheet controller to show window it's already making  
an assumption about the UI, which is none of its business.


Re-read my previous email. I explain at great length how to do this.  
Whether your sheet controller is called in one place or many different  
ones makes no difference. Get rid of all UI assumptions from the  
caller/client code, and make sure that all of the UI-based stuff is  
encapsulated in the sheet controller only. The callback to the client  
can be as simple as a single integer value if you want, but make sure  
that that is all it is, and you're not sneaking implementation details  
out and expecting the caller to rely on something that is private to  
the sheet controller.


There are also several examples of the architecture I explained in my  
demo app which I linked in the previous mail.


hth,

Graham





On 17 Jun 2008, at 3:51 am, John Love wrote:


Hello, Graham ...

Because I have multiple calls to show a sheet, from various parts of  
my
FileController, and because I wanted to make my sheet calls as  
general as
possible, I really .. really .. wanted to have a distinct  
SheetController.

As a result, I made calls from FileController to look like:[theSheet
showSheet:itsWindow], where theSheet was an outlet of FileController.

I could get away with that since all my sheets had just one  
button .. except
one, which had 3 buttons .. and for that exception, the asynchronous  
nature

of sheets got in the away.

I have not given up on a separate SheetController .. however .. I  
finally
reduced my showSheet routine to something very, very short and  
placed it in

FileController ..

- (void) showSheet: (NSWindow*)theSheet
   forWindow:(NSWindow*)theWindow
   withDescription:(NSString*)theDescription {

   if (theDescription) {
   if (theSheet == calculateSheet) {
   if (calculateDescription)  // NSTextField outlets of
FileController, 1 per sheet
   [calculateDescription setStringValue:theDescription];
   }
   else if (theSheet == saveSheet) {
   if (saveDescription)
   [saveDescription setStringValue:theDescription];
   }
   else if (theSheet == errorSheet) {
   if (saveDescription)
   [saveDescription setStringValue:theDescription];
   }
   }

   [NSApp beginSheet:theSheet
 modalForWindow:theWindow
 modalDelegate:nil
 didEndSelector:nil  //
@selector(sheetDidEnd:returnCode:contextInfo:)
 contextInfo:nil];
   itsReturnCode = [NSApp runModalForWindow:theSheet]; // (int)
itsReturnCode in FileController.h

   [NSApp endSheet:theSheet];
   [theSheet orderOut:self];

}

When I called showSheet, it looked like:
[self showSheet:calculateSheet forWindow:itsWindow
withDescription:nil]where calculateSheet, showSheet and errorSheet  
were 3

IBOutlets of FileController, all of class = NSWindow.

Every button of each sheet was connected to a specific IBAction of
FileController, e.g.,

- (IBAction) dontSaveIt:(id)sender {
  [self closeSheetWithCode:doCloseDoc];
}

with that last message looking like:

- (void) closeSheetWithCode:(int)theCode {

   [NSApp stopModalWithCode:theCode];

}

As the docs explain, when you do that, the message [NSApp
runModalForWindow:] returns that identical integer, which can be any  
integer

of your choosing.  In my case, the integer choices trigger a decision
whether to close the mainWindow after the sheet is closed, or  
whether to

keep mainWindow open after the sheet is closed.

I did not even have to mess with sheetDidEnd selectors because
closeSheetWithCode returned gave the needed flag I could use to  
quantify the

itsReturnCode instance variable of FileController.

Anyway, I have sheets, not the relatively antequated separate dialogs.

I have no intention of giving up on a separate SheetController ..  
but, in

the meantime, I have something that works.


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Prevent Asynchronous operation of beginSheetModalForWindow

2008-06-12 Thread Graham Cox

Hi John,

I hope you don't mind me cc'ing this to the list - I think it might be  
helpful to others (if not, my apologies for the noise).


On 12 Jun 2008, at 9:43 pm, John Love wrote:


Hi, Graham ...

Graham, this is a condensed summary of my initial communication:

Call it my fetish or whatever, but I strongly believe in  
compartmentalization, i.e., having a separate SheetController to do  
sheet stuff.


I'd say that was entirely reasonable.

For this purpose I have made SheetController*theSheet an outlet of a  
FileController*theFile and theFile is an outlet of my main nib's  
File's Owner.  Another outlet of File's Owner is my mainWindow. In  
MyDocument.m -awakeFromNib, I pass mainWindow to one of  
FileController's methods to initialize some stuff pertaining to  
mainWindow, including the most important setting of FileController's  
NSWindow *itsWindow, an instance variable.


Well, without being aware of the details, I can't be sure this is  
wrong or right - but I have to say, it smells. One strong principle of  
OOP design is that objects are responsible as far as possible for  
themselves and themselves alone. If you need to pass one object to  
another to put the first object into a useful state, that seems to be  
violating this principle. However, there are always exceptions and  
this may be one of them, hence my reluctance to say that it's  
definitely wrong.


Normally to control a window you use NSWindowController (or subclass  
of it) which already has a 'window' outlet, so there's no reason to  
have an 'itsWindow' outlet of your own. If another object needs the  
window (why?) then it should ask the window controller for it rather  
than keeping its own reference: [controller window];


Sometimes, I kinda have the feeling that the MVC implies one  
controller controls everything is the ideal.


Hmmm, not really. As many controllers as needed to make the design  
elegant and straightforward, but no more, would be my view. As simple  
as possible but no simpler.



Even though I am far from the end of my program's development, right  
now I have a total of 7 controllers, including the two already  
mentioned.  I also have a StatusController*theStatus which writes to  
a NSTextField of my main window.  The remaining 4 don't do very much  
right now.  Down the road I could conceivably shrink the 7 to 5 or  
whatever, but not much beyond that.  Before I continue, I would  
appreciate some feedback on this philosophy.  Considering my  
previous AppleScript Studio experience, I never had this  
philosophical problem; but now I do.



My approach has fallen into a common pattern, which I've grown  
comfortable with, and which I believe to be correct. Basically, one  
interface = one controller. This is strongly suggested by  
NSWindowController, which has an outlet for exactly one window. By  
interface I mean a single complete window or dialog box, where that is  
self-contained. If the dialog is complex and has multiple switchable  
views I might consider a separate controller for each one, though in  
practice I don't think I've ever done that - I've just put all the  
code for the entire dialog in one controller.


Let's suppose I have a document that owns a single main window  
controller - this is very typical in the document-based interface -  
but also has a number of additional dialog boxes that are needed to  
get certain operations done. The document is the nib's File's Owner,  
so it has outlets to each controller for each dialog box. Each  
controller in turn has outlets (and actions) for each individual  
widget/control in the dialog interface. What is a dialog for? It's to  
get information from the user in order to complete some task. The  
document is not interested in how that information is obtained  
specifically, it only knows it needs it. So the document asks the  
relevant controller go get me this information I need from the user.  
The dialog's controller in turn puts up the dialog, handles all the  
interaction with the user, removes the window when the user is done,  
packages up the information in a form useful to its client, and  
returns it. Everyone's happy - the document got its info, the dialog  
controller didn't have to care about who wanted the info or what was  
done with it, and the connections between the objects were kept to a  
minimum, with few dependencies.


Now whether the dialog is modal, modeless, a sheet, or whatever, is  
irrelevant. The controller for that dialog can probably make that  
decision (it may need to be given supplementary information, such as  
the parent window, but that can be designed into its interface with  
its client code - and it is also free to ignore it, so typically my  
dialog controllers take a parent window argument regardless, even if I  
end up ignoring it and displaying the dialog modally - the client  
(document) doesn't care either way). However, because the dialog may  
be modeless (or asynchronous, if you 

Prevent Asynchronous operation of beginSheetModalForWindow

2008-06-10 Thread John Love
Before I begin, I want to assure you that I have researched entries here on
sheets, as well as those in MacTech.com.  It's reasonably probable that I
have missed some entries and so that is why I am asking for help.

I also realize that this description is very long and I *really* did try to
shorten it.

My app is a Cocoa Document based app.

I have chosen the title Prevent Asynchronous operation of
beginSheetModalForWindow because I use various calls to
beginSheetModalForWindow in many parts of my app code and in one case I need
the calls to didEndSelector to be completed *before* the code that follows
beginSheetModalForWindow is executed (see MyDocument.m below).

With Asynchronous operation, the sheet will show for a very brief moment and
continue as the Apple docs stipulate .. I want the sheet to stay down UNTIL
I click one of the buttons in the sheet.

MacTech names calls to beginSheetModalForWindow DocModalNew.

What have I tried to do, but without success:

*1)* After the call to [calculateSheet beginSheetModalForWindow:docWindow ..
etc]; within showCalculateSheet, I have used:

while (itsReturnCode == -1)  // the initialized value before the call to
beginSheetModalForWindow

What happens is a never-ending loop from which I need to force-quit.

*2)* Within shouldCloseFile I have called:

while ((theReturnCode = [theSheet getReturnCode]) == -1);  // same
never-ending loop results

The app's File's Owner is MyDocument

// inside my nib file I have a NSObject named FileController and
SheetController

// in MyDocument.h
#import Cocoa/Cocoa.h
#import FileController.h

@interface MyDocument:NSDocument {
IBOutlet FileController*theFile;
IBOutlet NSWindow   *documentWindow;  // passed to methods in
FileController.m
}

// signatures of various methods here
@end

// in MyDocument.m

if ([theFile shouldCloseFile]) {

// stuff that canNOT be executed until shouldCloseFile finishes

}

==

// in FileController.h

#import Cocoa/Cocoa.h
#import SheetController.h

@interface FileController:NSObject {
IBOutlet SheetController *theSheet;
NSWindow *itsWindow;
}
- (BOOL) shouldCloseFile;
// plus other signatures
@end

==

// in FileController.m

// itsWindow is quantified elsewhere in this .m listing by anoter call
within MyDocument.m

- (BOOL) shouldCloseFile {
int theReturnCode;
BOOL shouldClose = TRUE;

if (!itsFinishedCalculation) {
[theSheet showCalculateSheet:itsWindow];

// tried this, but had to force-quit
 // while ((theReturnCode = [theSheet getReturnCode]) == -1);
theReturnCode = [theSheet getReturnCode];

if (theReturnCode == NSAlertFirstButtonReturn) { //
Continue
shouldClose = FALSE;
}
else if (theReturnCode == NSAlertSecondButtonReturn) {   // Stop
and save
[self saveFile];
NSLog(@NSAlertSecondButtonReturn);
}
}

return shouldClose;
}

==

// SheetController.h

#import Cocoa/Cocoa.h

@interface SheetController:NSObject {
NSWindow *itsWindow;   // passed to show methods
int  itsReturnCode;
}

- (int) getReturnCode;
- (void) showCalculateSheet:(NSWindow*)docWindow;
- (void) endCalculateSheet:(NSAlert*)theSheet
   returnCode:(int)returnCode
   contextInfo:(void*)contextInfo;
@end

==

// SheetController.m

#import SheetController.h

@implementation SheetController

- (id) init {
if (self = [super init]) {
 itsReturnCode = -1;
}

return self;
}


- (int) getReturnCode {
return itsReturnCode;
}


- (void) showCalculateSheet:(NSWindow*)docWindow {
NSButton *cButton, *sButton, *dButton;

itsWindow = docWindow;   // set instance variable
NSAlert *calculateSheet = [[[NSAlert alloc] init] autorelease];
[itsWindow setDelegate:calculateSheet];

cButton = [calculateSheet addButtonWithTitle:@Continue];
 // [cButton setKeyEquivalent:@\r];   // automatic for default button
sButton = [calculateSheet addButtonWithTitle:@Stop and save];
[sButton setKeyEquivalent:@s];
dButton = [calculateSheet addButtonWithTitle:@Stop and don't save];
[dButton setKeyEquivalent:@d];
[calculateSheet setMessageText:@You have not finished calculating your
Spreadsheet.\n
Do you wish to continue calculating?];
[calculateSheet setAlertStyle:NSWarningAlertStyle];

itsReturnCode = 1;
[calculateSheet beginSheetModalForWindow:docWindow modalDelegate:self
  didEndSelector:@selector
(endCalculateSheet:returnCode:contextInfo:)
  contextInfo:docWindow];
 // while (itsReturnCode == -1);  // tried this, but had to force-quit
}


- (void) endCalculateSheet:(NSAlert*)theSheet
   returnCode:(int)returnCode
   contextInfo:(void*)contextInfo {
if (returnCode == NSAlertFirstButtonReturn)// Continue

Re: Prevent Asynchronous operation of beginSheetModalForWindow

2008-06-10 Thread Michael Ash
On Tue, Jun 10, 2008 at 1:10 PM, John Love [EMAIL PROTECTED] wrote:
 I have chosen the title Prevent Asynchronous operation of
 beginSheetModalForWindow because I use various calls to
 beginSheetModalForWindow in many parts of my app code and in one case I need
 the calls to didEndSelector to be completed *before* the code that follows
 beginSheetModalForWindow is executed (see MyDocument.m below).

I'm sorry to have to tell you this, but you are doomed.

Sheets are inherently asynchronous. To understand why, think about
what happens when two sheets are displayed on two different windows.
The user can dismiss them in any order. What happens if sheet A
displays, then sheet B displays, then the user goes back and closes
sheet B? If there were a synchronous API the code would have to
somehow jump down the stack to where you're waiting for A, while
somehow leaving the stuff that's waiting for B live farther up the
stack. This is quite simply impossible in a C-based language.

Is there some reason you can't just put all of the after code in the
endCalculateSheet: method?

Mike
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Prevent Asynchronous operation of beginSheetModalForWindow

2008-06-10 Thread Jens Alfke


On 10 Jun '08, at 1:27 PM, Michael Ash wrote:


If there were a synchronous API the code would have to
somehow jump down the stack to where you're waiting for A, while
somehow leaving the stuff that's waiting for B live farther up the
stack. This is quite simply impossible in a C-based language.


It's not impossible, but it would require either that every window ran  
in a separate thread (as in the BeOS) or that the Cocoa frameworks  
supported coroutines. Coroutines are quite feasible in C, using setjmp/ 
longjmp style trickery; but when I investigated this I saw that using  
them would probably seriously confuse Objective-C's exception  
handling, and possibly NSRunLoop too.


John, you should look at the Cocoa conceptual docs that describe the  
use of sheets. There are probably a bunch of examples of sheet usage  
in the sample code too, if you search for beginSheetModalForWindow:.


—Jens

smime.p7s
Description: S/MIME cryptographic signature
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]

Re: Prevent Asynchronous operation of beginSheetModalForWindow

2008-06-10 Thread Graham Cox

Hi John,

While I understand to some extent why you've done it this way, you've  
also managed to tie yourself in knots here. Sheets are slightly more  
complex than running an old-school modal dialog inline but they are  
not as complicated as you seem to have made them!


The basic idea is that you have two pieces of code - one that triggers  
the sheet, and another that responds to it when the user closes it.  
You don't normally need anything more, though it may make sense to  
factor code into a controller object which can ease its re-use (but is  
not essential). You put all your code that runs after the dialog has  
completed in the completion routine.


One important thing to note is that you do not *ever* run a loop like:

while( returnCode == -1 ){ ... }

that's just crazy talk ;-) Don't attempt to somehow stall the main  
event loop until the sheet has finished - that will never work and  
sheets aren't designed to work that way.


Here's what I typically do, this would be code in a window controller  
dedicated to this sheet (warning - typed into Mail):



- (void)startSheetOnParent:(NSWindow*) parentWindow
{
/* set up the initial state of the sheet dialog here */

	[NSApp beginSheet:[self window] modalForWindow:parentWindow  
modalDelegate:self
		didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:)  
contextInfo:kSomeContextIdentifier];

}


- (void)	sheetDidEnd:(NSWindow*) sheet returnCode:(int) returnCode  
contextInfo:(void*) contextInfo

{
[sheet orderOut:nil];   // close the sheet

if ( returnCode == NSOKButton )
{
/*  process the result of the sheet here.
			If this method is shared with other sheets, you can use the  
contextInfo to

disambiguate the sheet.

			At this point just run the code that follows the sheet, or trigger  
it using a notification perhaps

*/
}
}


That's all you need. If your sheet has controls that interact with  
each other or external information, the 'modalDelegate' is the object  
that will handle that - again, it will be the sheet's controller.


If your calling code currently is arranged in such a way that it  
appears to you *necessary* to do something like:


- (void) doStuff
{
[mySheetController startSheetOnParent:[self windowForSheet]];

	while( sheetNotDone ){}		// spin hopelessly waiting for the sheet to  
finish - it never will because you've entered an infinite loop


if ( sheetResult == NSOKButton )
{
/* continue doing stuff */
}
}

then you need to refactor your code so that the 'keep doing stuff'  
part can be called directly from the sheet ended callback.


One thing that should be clear but maybe isn't is that the term  
'asynchronous' is a little misleading - the sheet is still being run  
on the same thread as the code that called it, so entering a while()  
loop waiting for the sheet to finish cannot possibly work - that loop  
will block the main thread so the sheet cannot continue to function,  
and there's nothing that could cause the loop to terminate. There is  
already a loop running that accomplishes this - the main event loop.


hth,


Graham





On 11 Jun 2008, at 6:10 am, John Love wrote:

Before I begin, I want to assure you that I have researched entries  
here on
sheets, as well as those in MacTech.com.  It's reasonably probable  
that I

have missed some entries and so that is why I am asking for help.

I also realize that this description is very long and I *really* did  
try to

shorten it.

My app is a Cocoa Document based app.

I have chosen the title Prevent Asynchronous operation of
beginSheetModalForWindow because I use various calls to
beginSheetModalForWindow in many parts of my app code and in one  
case I need
the calls to didEndSelector to be completed *before* the code that  
follows

beginSheetModalForWindow is executed (see MyDocument.m below).

With Asynchronous operation, the sheet will show for a very brief  
moment and
continue as the Apple docs stipulate .. I want the sheet to stay  
down UNTIL

I click one of the buttons in the sheet.

MacTech names calls to beginSheetModalForWindow DocModalNew.

What have I tried to do, but without success:

*1)* After the call to [calculateSheet  
beginSheetModalForWindow:docWindow ..

etc]; within showCalculateSheet, I have used:

   while (itsReturnCode == -1)  // the initialized value before the  
call to

beginSheetModalForWindow

   What happens is a never-ending loop from which I need to force- 
quit.


*2)* Within shouldCloseFile I have called:

   while ((theReturnCode = [theSheet getReturnCode]) == -1);  // same
never-ending loop results

The app's File's Owner is MyDocument

// inside my nib file I have a NSObject named FileController and
SheetController

// in MyDocument.h
#import Cocoa/Cocoa.h
#import FileController.h

@interface MyDocument:NSDocument {
   IBOutlet FileController*theFile