This is MiscController.m in view mode; [Download] [Up]
/*
MiscController.m
*/
// RCS identification information
static char *rcsID = "$Id:$";
static void __AvoidCompilerWarning(void) {if(!rcsID)__AvoidCompilerWarning();}
// NeXT Headers
#import <AppKit/AppKit.h>
// System Headers
// Other Headers
#import "MiscControllerManager.h"
// Superclass/Class Headers
#import "MiscController.h"
// Constants
NSString* MiscControllerDidEditNotification =
@"MiscControllerDidEditNotification";
@implementation MiscController
/*"
MiscController is the abstract superclass for all controllers.
(Controllers being somewhat like the controllers in a
model-view-controller setup). We also implement the interface
between controllers and controller managers.
Since MiscController is abstract, it shouldn't be instantiated
directly.
To become a part of the document framework we need a controller
manager. This is usually set in IB, though you can also use
#setControllerManager:. Inside #setControllerManager: we send
a message to our new controller manager to let it know about
ourselves. Once you have a controller manager you can ask it for
other controllers it knows about.
In the next verison, I will explain in detail the #isDirty,
#isEditable, #didEdit and #controllerDidEdit: methods. Most of
them are used in the little Adder miniexample if you just
can't wait for me to formally document them :-).
"*/
//-------------------------------------------------------------------
// Initialization/deallocation
//-------------------------------------------------------------------
- (id) init
/*"
Our designated initializer. Doesn't do much right now.
"*/
{
BOOL error = ([super init] == nil);
return error ? nil : self;
}
- (void) dealloc
/*"
Removes ourselve as an observer from the default notification
center, then releases any other resources we have. We don't
release our controller manager though, since we didn't retain
it.
"*/
{
// Stops the center from sending notification to what's going to be
// a freed object.
[[NSNotificationCenter defaultCenter] removeObserver:self];
[_name release];
[super dealloc];
}
//-------------------------------------------------------------------
// Accessor methods
//-------------------------------------------------------------------
- (MiscControllerManager*) controllerManager
/*"
Returns our controller manager. From it you can get all kinds of
information, like other controllers it knows about, or information
about our window, etc.
"*/
{
return _controllerManager;
}
- (void) setControllerManager:(MiscControllerManager*)newManager
/*"
Sets our controller manager to aManager. If we had an old
controller manager we first send it a #removeController:
method. We then add ourself to our new manager's controller
list via #addController. We don't retain our controller manager,
since that would introduce a cyclic reference. Raises an
NSInvalidArgumentException if the argument isn't a
MiscControllerManager or a subclass. (Maybe I shouldn't).
"*/
{
BOOL error = NO;
// Check arguments.
if (!error && newManager == nil) {
error = YES;
}
// Raise an exception if the argument is not nil but is also not a
// MiscControllerManager (or subclass).
if (!error && ![newManager isKindOfClass:[MiscControllerManager class]]) {
[NSException raise:NSInvalidArgumentException
format:@"The manager of a MiscController subclass must "
@"be an instance of a MiscControllerManager subclass. The "
@"instance presented was of class %@", [newManager class]];
error = YES;
}
if (!error) {
// If we have an old manager, let it know we have moved
// on.
[[self controllerManager] removeController:self];
// Let our new controller know about us.
[newManager addController:self];
// Set our own ivar, but don't retain it since that would create
// a cyclic reference.
_controllerManager = newManager;
}
}
- (BOOL) isDirty
/*"
Returns YES if we've changed in any way since we were last saved.
"*/
{
return _dirty;
}
- (void) setDirty:(BOOL)nowDirty
/*"
This will usually only be set by the controller itself. Calls on our
controller manager to update it's document edited status.
"*/
{
_dirty = nowDirty;
// The status of our controller manager may have changed
[[self controllerManager] updateDocumentEdited];
}
- (BOOL) isEditable
/*"
Not implemeted yet. Always returns YES.
"*/
{
return YES;
}
- (void) setEditable:(BOOL)nowEditable
/*"
Not implmented yet. For this to work correctly subclasses that
are going to be switching between editable and not editable
should extend this method to make their accompanying UI elements
either editable or not.
"*/
{
}
//-------------------------------------------------------------------
// MiscControllerDidEditNotification sender
//-------------------------------------------------------------------
- (void) didEdit
/*"
Posts a MiscControllerDidEditNotification with the receiver as
the notification's object. We also send a #setDirty:YES message to
ourself since editing usually makes us dirty. You should call this
method (or #didEditWithUserInfo:) any time you or one of your
UI elemetes are edited so other interested objects will know about it.
"*/
{
[self didEditWithUserInfo:nil];
}
- (void) didEditWithUserInfo:(NSDictionary*)userInfo
/*"
Does the same thing as #didEdit except it allows you to send along
userInfo with the posted notification. Of course the receivers of
the notification will have to be aware of the extra information and
what keys the NSDictionary contains (but then you probably already
knew that :-).
"*/
{
[self _postControllerDidEditNotificationWithUserInfo:userInfo];
[self setDirty:YES];
}
//-------------------------------------------------------------------
// Edit notification
//-------------------------------------------------------------------
- (void) controllerDidEdit:(NSNotification*)notification
/*"
Sent if you used our protected method
#_registerForControllerDidEditNotification: to register for notification
when another MiscController edits. Of course you can always register for
the MiscControllerDidEditNotification yourself through NSNotificationCenter
and use a method of your own choosing. This method currently does nothing
and is meant to be overridden in subclasses.
"*/
{
}
//-------------------------------------------------------------------
// Revert/Save (subclass responsibility)
//-------------------------------------------------------------------
- (BOOL) save
/*"
It is up to subclasses to override this method if their controller is
saveable (or you are going to use our controller manager's save method).
Return YES if the save was successful and NO otherwise. If for some
reason the save fails it is up to the controller to let the user know
why the failure occurred (through an alert panel I suppose). Also if the
save is successful make sure to call #setDirtry:NO in your implementation
of #save.
"*/
{
// This method needs to be overridden in a subclass.
[self doesNotRecognizeSelector:_cmd];
// To keep the compiler happy.
return NO;
}
- (BOOL) revert
/*"
See the description of #save for more useful information on saving
and reverting. This method must be overridden if the controller can
be reverted. It should return YES if the revert was successful and
NO otherwise. Make sure to call #setDirty:NO if the revert was
successful.
"*/
{
// This method needs to be overridden in a subclass.
[self doesNotRecognizeSelector:_cmd];
// To keep the compiler happy.
return NO;
}
//-------------------------------------------------------------------
// Support for named controllers
//-------------------------------------------------------------------
- (NSString*) name
/*"
Returns our controller's name.
"*/
{
return _name;
}
- (void) setName:(NSString*)newName
/*"
Sets our name to be newName. This allows you to ask a controller
manager for a controller without keeping an outlet to it (See
MiscControllerManager's #{controller(s)WithName:}). We copy
newName and autorelease the previous name.
"*/
{
[_name autorelease];
_name = [newName copy];
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.