• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Hanging Indentation in NSTextField
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Hanging Indentation in NSTextField


  • Subject: Re: Hanging Indentation in NSTextField
  • From: Ryan Stevens <email@hidden>
  • Date: Thu, 30 Mar 2006 08:05:04 -0800


On Mar 29, 2006, at 6:07 AM, Greg Wiseman wrote:

Hi, I'm relatively new to Cocoa and brand new to this list. I have a
question about laying out text in an NSTextField.

I have a grid of NSTextFields. The fields wrap and change height based
on the number of lines of text in them. I would like to automatically
indent lines of text after the first line to visually distinguish
fields in the same column from each other (i.e. have the NSTextFields
lay out their automatically wrapped contents using hanging
indentation).

I've looked over (and been somewhat overwhelmed by) Apple's Text
Layout documentation
(http://developer.apple.com/documentation/Cocoa/Conceptual/ TextLayout/index.html)
and tried delving into the documentation for what seem to be the
relevant classes: NSLayoutManager, NSTypesetter, NSTextContainer, and
NSTextView. I've tried a few different solutions but nothing works
quite right.


I'm fairly sure I need to be using a subclass of NSTextContainer,
let's call it ReverseIndentationTextContainer. It contains one
instance variable: a float to store the indentation level (in pixels)
and relevant accessors, and it overrides
lineFragmentRectForProposedRect as follows:

- (NSRect)lineFragmentRectForProposedRect:(NSRect)proposedRect
sweepDirection:(NSLineSweepDirection)sweepDirection
movementDirection:(NSLineMovementDirection)movementDirection
remainingRect:(NSRect *)remainingRect;
{
	if (proposedRect.origin.y > 0) {
		proposedRect.origin.x += [self indentation];
	}
	return [super lineFragmentRectForProposedRect:proposedRect
sweepDirection:sweepDirection movementDirection:movementDirection
remainingRect:remainingRect];
}

So the question now is how to hook this into the app so it gets used.

Since we're dealing with textfields, it seems to make sense that we
need to attach it to the field editor. I tried simply calling
replaceTextContainer: on the field editor when editing of the fields
begins, in the textfield delegate's controlTextDidBeginEditing method.
It works beautifully until editing finishes, then the lines are no
longer indented.

Perhaps I need to subclass NSTextView and create a custom field editor
for the relevant fields? I also tried doing this. My subclass looks as
follows:

@interface ReverseIndentationFieldEditor : NSTextView {
	ReverseIndentationTextContainer *textContainer;
	float REVERSE_INDENTATION = 20.0;
}
@end
@implementation ReverseIndentationFieldEditor
-(id)init;
{
	if ( self = [super init] ) {
		[self setFieldEditor:YES];
		textContainer = [[ReverseIndentationTextContainer alloc] init];
		[textContainer setIndentation:REVERSE_INDENTATION];
		[self replaceTextContainer:textContainer];
	}
	return self;
}
-(void)dealloc;
{
	[textContainer release];
	[super dealloc];
}
@end

I tried returning this field editor from my window delegate's
windowWillReturnFieldEditor method as follows:

- (id)windowWillReturnFieldEditor:(NSWindow *)sender toObject:(id) anObject;
{
if ( [[[anObject cell] representedObject]
isKindOfClass:[ReverseIndentContent class]] ) {
if (!reverseIndentFieldEditor)
reverseIndentFieldEditor = [[ReverseIndentFieldEditor alloc] init];
return reverseIndentFieldEditor;
}
return nil;
}


but had no luck. Same problem as before, only now the text fields
don't seem to honour the setWrap flag I pass in.

The latest thing I've tried doing is subclassing NSTextField and
NSTextFieldCell so I can hook in my NSTextView subclass through them,
overriding the following method in NSTextFieldCell:

- (NSText *)setUpFieldEditorAttributes:(NSText *)textObj;
{
	textObj = [super setUpFieldEditorAttributes:textObj];
	ReverseIndentationTextContainer *container =
[[ReverseIndentationTextContainer alloc] init];
	[container setIndentation:20.0];
	[(NSTextView*)textObj replaceTextContainer:container];

	return textObj;
}

My NSTextField subclass is empty and exists solely so I can call
setCellClass: on it and assign it my custom cell class.

Nevermind the fact that the above code is horribly wasteful and
allocates a new field editor for each textfield - I'm still just
experimenting. This does pretty much the same thing as setting the
field editor in the window delegate, as you might expect.

So, obviously I have no idea what I'm doing.

Thanks in advance for any help.
-Greg

I would use NSAttributedStrings instead. Make a NSMutableParagraphStyle with 5 or 10 for its headIndent and reuse/ apply that to each NSAttributedString before giving them to your text fields...


NSParagraphStyle, -headIndent ...
Returns the distance in points from the leading margin of a text container to the beginning of lines other than the first.


Sounds like it'll do exactly what you want. :D
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden


  • Follow-Ups:
    • Re: Hanging Indentation in NSTextField
      • From: Douglas Davidson <email@hidden>
References: 
 >Hanging Indentation in NSTextField (From: "Greg Wiseman" <email@hidden>)

  • Prev by Date: Re: [NSapp mainMenu] returns nil
  • Next by Date: Re: NSImage Path
  • Previous by thread: Hanging Indentation in NSTextField
  • Next by thread: Re: Hanging Indentation in NSTextField
  • Index(es):
    • Date
    • Thread