Challenge 2, boldface/italic letters *SPOILER* contains code


#1

So, anyone here who completed the bold/italic challenge?

I did but my code looks kind of ugly :frowning: that’s why I wanted to ask how you guys did it

// BigLetterView.h
// ...
BOOL bold, italic;
// ...
// BigLetterView.m
// ...
// Challenge 2, Page 286, Add bold and italic checkboxes
- (IBAction)boldCheckbox:(id)sender
{
	bold = !bold;
	[self setNeedsDisplay:YES];
}

- (IBAction)italicCheckbox:(id)sender
{
	italic = !italic;
	[self setNeedsDisplay:YES];
}

- (void)drawRect:(NSRect)dirtyRect {
// ...
	// do some font formatting
	NSFontManager *fontManager = [NSFontManager sharedFontManager];
	NSFont *oldFont = [attributes valueForKey:NSFontAttributeName];
	NSFont *newFont = nil;
	
	NSFontTraitMask oldMask = [fontManager traitsOfFont:oldFont];
	
	if (bold && !(oldMask & NSBoldFontMask)) {
		// we want bold, but it's not set yet
		newFont = [fontManager convertFont:oldFont
					  toHaveTrait:NSBoldFontMask];
	} else if (!bold && (oldMask & NSBoldFontMask)) {
		// we don't want bold, but it's set
		newFont = [fontManager convertFont:oldFont
				   toNotHaveTrait:NSBoldFontMask];
	}
	
	if (italic && !(oldMask & NSItalicFontMask)) {
		// we want italic, but it's not set yet
		newFont = [fontManager convertFont:oldFont
					  toHaveTrait:NSItalicFontMask];
	} else if (!italic && (oldMask & NSItalicFontMask)) {
		// we don't want italic, but it's set
		newFont = [fontManager convertFont:oldFont
				   toNotHaveTrait:NSItalicFontMask];
	}
	
	if (newFont) {
		NSLog(@"font changed");
		[attributes setObject:newFont forKey:NSFontAttributeName];
	}
	
	[self drawStringCenteredIn:bounds];
// ...

I also tried to play with NSUnboldFontMask/NSUnitalicFontMask to get rid of the toNotHaveTrait: calls, but that didn’t work as expected…

EDIT: remove unnecessary if
EDIT: added spoiler warning


#2

I referred to the original post on the old board.
techstra.bignerdranch.com/Home page 286

but your code looks fine to me and it works.
I just added

if (mybold && !(oldMask & NSBoldFontMask)) { // we want bold, but it's not set yet newFont = [fontManager convertFont:oldFont toHaveTrait:NSBoldFontMask]; -------> oldFont = newFont; } else if (!mybold && (oldMask & NSBoldFontMask)) { // we don't want bold, but it's set newFont = [fontManager convertFont:oldFont toNotHaveTrait:NSBoldFontMask]; --------> oldFont = newFont; }

So it would be bold and italics.
Thanks for posting the SPOILER it helped a lot.

ps. I added a CGFloat newSize = (r.size.width * 0.2678);
[attributes setObject:[NSFont fontWithName:@"Helvetica"
size:newSize]
forKey:NSFontAttributeName];

to scale the font to the window size proportionally cuz I’m just that way… :wink:


#3

[quote=“IanDMah”]I referred to the original post on the old board.
techstra.bignerdranch.com/Home page 286

but your code looks fine to me and it works.
I just added

if (mybold && !(oldMask & NSBoldFontMask)) { // we want bold, but it's not set yet newFont = [fontManager convertFont:oldFont toHaveTrait:NSBoldFontMask]; -------> oldFont = newFont; } else if (!mybold && (oldMask & NSBoldFontMask)) { // we don't want bold, but it's set newFont = [fontManager convertFont:oldFont toNotHaveTrait:NSBoldFontMask]; --------> oldFont = newFont; }

So it would be bold and italics.
Thanks for posting the SPOILER it helped a lot.

ps. I added a CGFloat newSize = (r.size.width * 0.2678);
[attributes setObject:[NSFont fontWithName:@"Helvetica"
size:newSize]
forKey:NSFontAttributeName];

to scale the font to the window size proportionally cuz I’m just that way… :wink:[/quote]

hm I didn’t find anything bold/italic/font/chapter 20 related at the old “forum”…

Anyway, could you elaborate why you’re doing oldFont = newFont; ?

PS: changing the font size as you resize the window is a nice idea :slight_smile:


#4

ok, I got how techstra.bignerdranch.com/ works now

I always thought each and every comment is on the first page (d’oh!) and never even had the idea to insert a page number in the “Page #” field (d’oh! again)


#5

I realise this thread is old, but some newbie like me might still come along & find this useful.
I checked out the old thread as well as what was posted here and found most of it to be unnecessarily complicated.
So here is what I came up with, which goes into the drawRect method:

[code] NSFontManager *fontManager = [NSFontManager sharedFontManager];
NSFont *theFont = [attributes objectForKey:NSFontAttributeName];
theFont = [fontManager convertFont:theFont toHaveTrait:
(boldFont ? NSBoldFontMask : NSUnboldFontMask) |
(italicFont ? NSItalicFontMask : NSUnitalicFontMask)];
[attributes setObject:theFont forKey:NSFontAttributeName];

[self drawStringCenteredIn:bounds];

[/code]

You don’t have to know whether the font is already bold &/or italic and this sets bold/unbold and italic/unitalic as specified by the 2 Booleans: boldFont & italicFont.
These are changed in actions of the checkboxes, which look like this (changeItalic is the same, only setting italicFont):

- (IBAction)changeBold:(id)sender { boldFont = [sender state]; [self setNeedsDisplay:YES]; }