Re: Toolbar code in separate Controller?
Re: Toolbar code in separate Controller?
- Subject: Re: Toolbar code in separate Controller?
- From: "John Love" <email@hidden>
- Date: Tue, 15 Jul 2008 09:13:26 -0400
As some of you realize, I have a fetish about compartimentalization, that
is, the making of separate files(.h,.m) as much as possible ... and I
erroneously concluded that the only way to do that was via the construction
of multiple Controllers within IB. It turns out that that is one means when
it logically makes sense, as in the following:
Graham Cox "crammed" down me a lot of info about isolating the
SheetController(delegate) from the calling Controller, the delegat*or*; for
example, keeping the GUI data isolated within the SheetController and away
from the delegator. I also learned about anonymous callback id pointers
that allowed me to create a separate Controller for calling sheets. My
delegator, FileController, called my separate SheetController via the
latter's ShowSheet method. I passed *self* from FileController as the
delegator to ShowSheet, within which the passed delegator was typed as an
anonymous id at the top of SheetController's implementation file.
- (void) showSheet:(NSWindow*)parentWindow
delegator:(id)theDelegator
contextInfo:(void*)contextInfo {
mFileCtrlDelegator = theDelegator; // typed as id at the top
[NSApp beginSheet:[self window]
modalForWindow:parentWindow
modalDelegate:self
didEndSelector:@selector
(sheetDidEnd:returnCode:contextInfo:)
contextInfo:contextInfo];
[NSApp runModalForWindow:[self window]];
}
Within SheetController's sheetDidEnd, I call:
[mFileCtrlDelegator doSheetSelection:returnCode
contextInfo:contextInfo];
Since mFileCtrlDelegator is anonymous-ly typed as an id pointer within my
showSheet, I include the informal protocol:
@interface NSObject (SheetController)
- (void) doSheetSelection:(int)returnCode
contextInfo:(void*)contextinfo;
@end
within SheetController's interface file. The protocol is deliberately
anonymous to match showSheet's theDelegator so I do not get a compile
error. The *real* doSheetSelection: lives in my delegator, FileController.
The anonymous id pointer is resolved at run-time, thus calling the *real*,
i.e. FileController's, doSheetSelection. Everything works just as Graham
Cox taught ... and the real miracle is I believe I finally understand it,
and everything else Graham taught me.
My next challenge was to get various Menu Items to dim or not, depending on
the values of certain instance variables within that same FileController
object ... which is the only IBOutlet of MyDocument that I created.
As stated at the top, I erroneously concluded that the only way to achieve
compartimentalization (separate files) was via the creation of separate
Controllers within IB ... *wrong* ... and that is when I came across
Categories, and Extensions.
At the discovery of Categories, I noted Apple's words "You can also use
categories to distribute the implementation of a new class into separate
source files—for example, you could group the methods of a large class into
several categories and put each category in a different file."
God is good ... I can compartimentalize (or, make separate files) using
separate Controllers as in Sheets, or via categories ... and I needed
categories because otherwise I would have had to play with the Responder
Chain had I chosen a separate Controller and, quite frankly, I do not know
how to do that. MyDocument is already in the Responder Chain, so leave
well-enough alone.
So, I then created "MyDocument+MenuCategory"(.h,.m), within which I override
Apple's validateMenuItem: to use the values of several instance variables of
FileController to enable or disable one or more of the several MenuItems.
If I had any instance variables unique to MenuCategory, I would have to
place them in the main MyDocument.h because only instance methods are
permitted in the category's interface. Within the category method I can
access the instance variables of FileController because the FileController
object is the only outlet of MyDocument (or the "root") that I created.
Not only do categories work, but I also believe that I understand them. I
view a category as an "addition" whereby unique capabilities or actions are
added to the "root". MyDocument is the "root" and MenuCategory is the
"addition". The "root" has all the required instance variables (the
original plus those added for the "addition"), and the "addition" adds new
actions using the added instance variables. I'm tempted to use "extension",
instead of "addition" because "extension" is really more meaningful, at
least for me. However, Apple uses "extension" to mean something a little
bit different, as explained in Apple's Objective-C pdf.
The validateMenuItem: message is sent to the File's Owner = MyDocument,
which is the "root" that has been added to .. and it is the File's Owner
that is the target of the menu actions.
The "category" is not a new, separate class, just an addition to the
alrady-existing class. It would be very tempting here to call the
"category" a sub-class, except the latter can store not only unique methods,
but also its own instance variables which a "category" cannot have in its
interface. These added instance variables must be at the "root" of the
"category".
My current challenge addresses the enabling, or disabling, of my several
ToolbarItems via Apple's validateToolbarItem: method ... the subject adds
"extensions" to the mix.
I have within "MyDocument+ToolbarCategory.h":
@interface MyDocument (ToolbarCategory)
// for example
(void) setupToolbar:(NSWindow*)theWindow;
@end
and have added toolbar-unique instance variables to MyDocument(the "root"),
such as:
IBOutlet NSToolbarItem *saveSpreadsheetItem;
So the new "category" is complete … but what about:
(BOOL) validateToolbarItem:(NSToolbarItem*)theItem;
which Apple states "is sent to validators for each visible NSToolbarItem
with a valid target/action pair.". Apple continues:
"NSToolbarItemValidation *extends*(emphasis added) the standard validation
idea by introducing this new method which is sent to validators for each
visible standard NSToolbarItem with a valid target/action pair.
"Standard items validate themselves by sending the validateToolbarItem:
validate message to the current validator. Since items with custom views
don't always have meaningful target/actions, they do nothing. So for your
custom items it may be useful to override this method and invent your own
validation."
So, here, we make MyDocument the current validator – on "first blush", this
syntax appears to say that NSToolbarValidation is a *new* "category" of, or
"addition" to MyDocument:
@interface MyDocument (NSToolbarItemValidation)
- (BOOL) validateToolbarItem:(NSToolbarItem*)toolbarItem;
@end
Within "MyDocument+ToolbarCategory.m" we add:
// Here, we make MyDocument the current validator.
// Our MyDocument has a new category = NSToolbarItemValidation (??):
@implementation MyDocument (NSToolbarItemValidation)
- (BOOL) validateToolbarItem:(NSToolbarItem*)toolbarItem {
BOOL enable = NO;
// NSLog(@"validateToolbarItem"); // success!
if ([[toolbarItem itemIdentifier] isEqual:OpenDocToolbarItemIdentifier])
{
if ([iboFileCtrl fileFinishedCalculation]) enable = YES;
}
else if ([[toolbarItem itemIdentifier]
isEqual:SaveDocToolbarItemIdentifier])
{
// iboFileCtrl is my single IBOutlet for MyDocument
// Thanks! Graham for the lesson on naming conventions.
if (![iboFileCtrl fileSaved]) enable = YES;
}
else if ([[toolbarItem itemIdentifier]
isEqual:StopDocToolbarItemIdentifier])
{
if (![iboFileCtrl fileFinishedCalculation]) enable = YES;
}
return enable;
}
@end
To tell you the truth, I *really* prefer calling a category an extension
because "extension" just sounds more meaningful to me. Or, maybe just
plain, ole, generic "addition". "Category" just sounds like "type of" or a
sub-class, but it's not that at all.
Yes, we're discussing words, but words are important .. Look up "category"
in a dictionary where it talks about classification. To me, classification
means sub-class.
An antelope is a type of animal. Way at the beginning of all this, I am
adding to or extending MyDocument to include menu stuff. Menu stuff is not
a "type of" MyDocument.
Back to NSToolbarItemValidation .. it is not a "type of" MyDocument. So,
based on the above, I should not call it a "category" of MyDocument. So
what do I call it? Is it an "extension" of MyDocument?
Apple states " NSToolbarItemValidation extends the standard validation idea
..". In Apple's Objective-C pdf, Apple sttates "Class extensions are like
'anonymous' categories ..".
I've reached a road block here .. Apple says "extends the standard
validation idea", yet:
@interface MyDocument (NSToolbarItemValidation)
implies that NSToolbarItemValidation extends MyDocument.
I stand at a road block .. would appreciate some help here!
Cheers,
John Love
_______________________________________________
Cocoa-dev mailing list (email@hidden)
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:
This email sent to email@hidden