Creating an RTF Class

Using Rich Text can be a pain: you have to remember far too many controls. There’s got to be an easier way! Of course there is — create an Objective-C class for building and managing Rich Text segments. Following is the interface for such a class, a subclass of the root NSObject class, which works with the NSTextView object:

#import <Cocoa/Cocoa.h>

@interface RTF:NSObject
{
    NSMutableData *data;
}
- (void)dealloc;
- (NSData *)data;
- (void)appendChar:(unsigned char)ch;
- (void)appendRTF:(NSString *)string;
- (void)appendString:(NSString *)string;
- (void)setBold:(BOOL)flag;
- (void)setJustify:(NSTextAlignment)mode;
- (void)setSize:(float)aSize;

@end

This time we’ll describe these methods before we show how they are coded. The interface and method descriptions are all you really need to know in order to use a class — we don’t need to know the implementation details. For example, we don’t know how the AppKit classes are implemented, yet we’ve been using them throughout the book!

Table 12-3 summarizes the instance methods declared in our new RTF class. The methods described in this table that do not appear in RTF.h are overrides of methods in NSObject.

Table 12-3. Instance methods in the RTF class

Method

Method description

(id)init

Initializes an RTF object, establishes a simple Rich Text header, and returns the id of the newly created RTF object.

(void)dealloc

Frees the RTF object and releases its internal storage.

(NSData *)data

Returns an NSData object for an RTF object. The RTF data is automatically terminated by a closing brace character. You can pass this object directly to an NSTextView object’s replaceCharactersInRange:withRTF: method. This method doesn’t actually return the internal NSData buffer; instead, it returns a copy.

(void)appendChar:(unsigned char)ch

Appends a character to the internal NSData object.

(void)appendRTF:(NSString *)string

Appends a Rich Text string to the RTF object stream. No translation is performed on the string.

appendString:(NSString *)string

Appends an ASCII text string to the RTF object stream. Special characters, such as newline and backslash, are automatically quoted.

setBold:(BOOL)flag

If flag is YES, the following text is appended in bold. If flag is NO, the following text is not appended in bold.

setJustify:(NSTextAlignment)mode

Sets the justification mode of the text that is appended to the RTF object. Cocoa’s justification modes are defined in the header file NSText.h.

Following is the implementation for our RTF class:

// RTF.m:

#import "RTF.h"

@implementation RTF
- (id)init
{
    NSString *header = 
     @"{\rtf1\mac{\fonttbl\f0\fswiss Helvetica;}\f0\fs24 ";

    [super init];
    data = [NSMutableData dataWithData:
             [header dataUsingEncoding:NSASCIIStringEncoding] ];
    [data retain];
    return self;
}

- (void)dealloc
{
    [data release];
    return [super dealloc];
}

// Create a new NSData object that has a termination brace.
// Cocoa's NSText won't display without the brace.
- (NSData *)data
{
   NSMutableData *data2 = [[NSMutableData alloc]
                           initWithData:data];
   [data2 appendBytes:"}" length:1];
   return data2;
}

// appendChar: appends an arbitrary character to the data
- (void)appendChar:(unsigned char)ch
{
    [data appendBytes:&ch length:1];
}

// appendRTF: appends an arbitrary RTF string to the RTF object
- (void)appendRTF:(NSString *)string
{
   [data appendData: [string dataUsingEncoding:NSASCIIStringEncoding] ];
}

// appendString: appends an ASCII text string,
// all of the special characters in the text
- (void)appendString:(NSString *)string
{
    int i;

    for (i=0;i<[string length];i++) {
        unichar c = [string characterAtIndex:i];

        switch(c) {
          case '
':   // escape special characters
          case '{':
          case '}':
          case '':
             [self appendChar:''];
             break;
          default:
            break;
        }
        [self appendChar:c];
    }
}

- (void)setBold:(BOOL)flag
{
    [self appendRTF: flag ? @"\b " : @"\b0 "];
}

- (void)setSize:(float)aSize
{
    [self appendRTF:[NSString stringWithFormat:@"\fs%d",(int)aSize*2]];
}

- (void)setJustify:(NSTextAlignment)mode
{
    switch(mode) {
      case NSNaturalTextAlignment:
      case NSLeftTextAlignment:
      case NSJustifiedTextAlignment:
         [self appendRTF:@"\ql
"];
         break;
      case NSCenterTextAlignment:
         [self appendRTF:@"\qc
"];
         break;
      case NSRightTextAlignment:
         [self appendRTF:@"\qr
"];
         break;
    }
}

@end

This class makes use of the NSMutableData and NSString classes, and of Cocoa’s Unicode-based system for converting between the two. If you are not familiar with these classes, you may find it useful to review their documentation at this time.

Notice that, before the NSData is returned, a copy is made and the closing brace (}) required by the Rich Text standard is appended. The closing brace is added to the copy, which allows the RTF object itself to be used again should the caller wish to add more information. (PaperController won’t, but you might in another program that you write.) The object’s user doesn’t have any way of knowing that this is done, and indeed, as long as the RTF class works properly for the user, the user doesn’t need to know. This is another example of why it is better to use accessor methods rather than using Objective-C’s @public feature and directly accessing an object’s instance variables.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.189.228