NSTextView indentation - cocoa

ALL,
Apple documentation here talks about 3 function on setting indentation.
I did use them and I even called:
[attrs setValue: paragraphStyle forKey: NSParagraphStyleAttributeName];
[m_textView setTypingAttributes: attrs];
but unfortunately pressing Enter at the end of the text does not indent the cursor.
Below is a complete code:
paragraphStyle = [[NSMutableParagraphStyle alloc] init];
[paragraphStyle setFirstLineHeadIndent: indent];
[paragraphStyle setHeadIndent: indent];
[storage addAttribute: NSParagraphStyleAttributeName value: paragraphStyle range: range];
if( range.length == 0 )
{
[attrs setValue: paragraphStyle forKey: NSParagraphStyleAttributeName];
[m_textView setTypingAttributes: attrs];
}
[paragraphStyle release];
It works when I have a selection in the text (range.length > 0), but when I try to set it, go to the end of the text and press Enter, cursor still goes to the column 1 (not indenting).
What am I missing?
I think it is called auto-indenting so I will add that tag as well. Please remove if I'm wrong.
TIA!
[EDIT]
Trying to add:
[m_textView setDefaultParagraphStyle:paragraphStyle];
does not do anything.
When there is no selection and I hit Enter at the end of the text, cursor still jump to the position at the beginning of the line.
[/EDIT]
[EDIT2]
I modified my code as follows:
if( style.HasLeftIndent() )
{
if( start == end && start == 0 )
range = NSMakeRange( 0, 1 );
else if( start == end && start == storage.string.length )
range = NSMakeRange( start - 1, start );
else if( start == end )
range = NSMakeRange( start, start + 1 );
paragraphStyle = [[NSMutableParagraphStyle alloc] init];
[paragraphStyle setFirstLineHeadIndent: indent];
[paragraphStyle setHeadIndent: indent];
[storage addAttribute: NSParagraphStyleAttributeName value: paragraphStyle range: range];
if( /*start == -1 && end == -1*/range.length == 0 )
{
[attrs setValue: paragraphStyle forKey: NSParagraphStyleAttributeName];
[m_textView setDefaultParagraphStyle:paragraphStyle];
[m_textView setTypingAttributes: attrs];
}
[paragraphStyle release];
}
Now let's say my text contains following:
Big brown fox jumps over the lazy dog.\n
If I have my cursor sitting right after the dot and there is no selection the program crashes. It looks like the range variable is incorrect.
[/EDIT2]
[EDIT3]
My current code is:
if( start == end && start == 0 )
range = NSMakeRange( 0, 1 );
else if( start == end && start == storage.string.length )
range = NSMakeRange( start - 1, 1 );
else if( start == end )
range = NSMakeRange( start, 1 );
paragraphStyle = [[NSMutableParagraphStyle alloc] init];
[paragraphStyle setFirstLineHeadIndent: indent];
[paragraphStyle setHeadIndent: indent];
[storage addAttribute: NSParagraphStyleAttributeName value: paragraphStyle range: range];
if( /*start == -1 && end == -1*/range.length > 1 )
{
[attrs setValue: paragraphStyle forKey: NSParagraphStyleAttributeName];
[m_textView setDefaultParagraphStyle:paragraphStyle];
[m_textView setTypingAttributes: attrs];
}
[paragraphStyle release];
[/EDIT3]
[EDIT4]
This is my latest code:
NSMutableDictionary *attrs = [NSMutableDictionary dictionaryWithCapacity:5];
if( style.HasLeftIndent() )
{
if( start == end && start == 0 )
range = NSMakeRange( 0, 1 );
else if( start == end )
range = NSMakeRange( start - 1, 1 );
paragraphStyle = [[NSMutableParagraphStyle alloc] init];
[paragraphStyle setFirstLineHeadIndent: indent];
[paragraphStyle setHeadIndent: indent];
[storage addAttribute: NSParagraphStyleAttributeName value: paragraphStyle range: range];
{
[attrs setValue: paragraphStyle forKey: NSParagraphStyleAttributeName];
[m_textView setDefaultParagraphStyle:paragraphStyle];
[m_textView setTypingAttributes: attrs];
}
[paragraphStyle release];
}
this code works if my cursor sits at the beginning of the paragraph.
However if I'm in the middle of itor in the end of there is no indentation.
The paragraph being the text after new-line symbol or Enter press.
What am I doing wrong?
[/EDIT4]
[EDIT5]
This is my last code:
if( style.HasLeftIndent() )
{
if( start == end && start == 0 )
range = NSMakeRange( start, start + 1 );
else
range = [[m_textView textStorage].string paragraphRangeForRange: NSMakeRange( end - 1, 1 )];
paragraphStyle = [[NSMutableParagraphStyle alloc] init];
[paragraphStyle setFirstLineHeadIndent: indent];
[paragraphStyle setHeadIndent: indent];
[storage addAttribute: NSParagraphStyleAttributeName value: paragraphStyle range: range];
if( /*start == -1 && end == -1*/range.length == 0 )
{
[attrs setValue: paragraphStyle forKey: NSParagraphStyleAttributeName];
[m_textView setDefaultParagraphStyle:paragraphStyle];
[m_textView setTypingAttributes: attrs];
}
[paragraphStyle release];
}
It is almost perfect. The only thing missing is following:
Again my text is:
The brown fox jumps over the lazy dog.\n\n
There are 2 empty lines after the text. When my cursor is set on the top new new line this code indent the text on the first line. What I'd like is the text to stay non-indented, but the cursor jumps to the right, so that newly entered text becomes indented.
And the same should happen when my cursor at the second empty line.
[/EDIT5]
What am I missing?

Related

IBAction float, have a equal different numbers depending on input

New to objective-c and I just can't find the answer to this question anywhere. I'm running a IBAction for a calculation but I need the input from a label to actually equal something else in the equation.
For example:
-(IBAction)calculate; {
float a = 1.05 if ([label1.text] == 1in);
a = 2.07 if ([label1.text] == 2in);
a = 3.07 if ([label1.text] == 3in);
float b = a*([textField1.text floatValue]);
label2.text = [[NSString alloc] initWithFormat:#"%2.f", b];
}
I know I'm not even close to getting it right but I hope you get the idea as to what I'm looking for.
Thank you!
- (void)calculate {
float a;
if ([self.inputField.text isEqualToString:#"1in"]) a = 1.05f;
else if ([self.inputField.text isEqualToString:#"2in"]) a = 2.07f;
else if ([self.inputField.text isEqualToString:#"3in"]) a = 3.07f;
else a = 0.0f;
if (a) {
float b = a * ([self.inputField.text floatValue]);
self.inputField.text = [[NSString alloc] initWithFormat:#"%.2f", b];
}
else self.inputField.text = #"Invalid";
}
- (void)viewDidLoad
{
//...
self.inputField = [[UITextField alloc] initWithFrame:CGRectMake(10.0f, 20.0f, 300.0f, 30.0f)];
[self.inputField setBackgroundColor:[UIColor grayColor]];
[self.view addSubview:self.inputField];
UIButton * doneButton = [[UIButton alloc] initWithFrame:CGRectMake(10.0f, 55.0f, 300.0f, 30.0f)];
[doneButton setBackgroundColor:[UIColor blackColor]];
[doneButton setTitle:#"Done" forState:UIControlStateNormal];
[doneButton addTarget:self action:#selector(calculate) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:doneButton];
[doneButton release];
}
Note: I replaced the output format %2.f to %.2f, cause I guess you may need this format. E.g:
Input > 1in
Output< 1.05
Input > 2in
Output< 4.14
Input > 3in
Output< 9.21

How do i get the range of the current paragraph in a NSTextView where the cussor stayed there?

Now i need to change the alignment of a paragraph in a nstextview without select it ,so i need to know the range of the current range of the paragraph?
I have a subclass of NSTextView so you need to access textStorage and selectedRange different than [self textStorage] and [self selectedRange].
NSTextStorage *textStorage = [self textStorage];
NSString *string = [textStorage string];
NSUInteger editEnd = [self selectedRange].location;
NSUInteger editStart = editEnd-[textStorage editedRange].length;
NSUInteger maxLength = [string length];
while (editStart > 0) {
unichar theChr = [string characterAtIndex:editStart-1];
if( theChr == '\n' || theChr == '\r' ) {
break;
}
--editStart;
}
while (editEnd < maxLength) {
unichar theChr = [string characterAtIndex:editEnd];
if( theChr == '\n' || theChr == '\r' ) {
break;
}
++editEnd;
}
NSRange paragraphRange = NSMakeRange(editStart, editEnd-editStart);
Here's a shortcut:
NSRange paragraphRange = [textView.textStorage.string paragraphRangeForRange: [textView selectedRange]];
First, get the range where the cursor stayed through [textView selectedRange]
Then you can get the line range through - (NSRange)lineRangeForRange:(NSRange)range of [textView string]
Here is a example code:
NSRange sel = [textView selectedRange];
NSString *viewContent = [textView string];
NSRange lineRange = [viewContent lineRangeForRange:NSMakeRange(sel.location,0)];
detail in there.
How to get the selected line range of NSTextView?

optimize core-data fetchrequest

Dear Community.
I have some issues, where i have to compare digits in core data with decreased range.
here is a first part of code:
NSFetchRequest *requestDestinationWeBuy = [[[NSFetchRequest alloc] init] autorelease];
[requestDestinationWeBuy setEntity:[NSEntityDescription entityForName:#"DestinationsListWeBuy"
inManagedObjectContext:moc]];
NSError *error = nil;
[requestDestinationWeBuy setPredicate:
[NSPredicate predicateWithFormat:
#"carrier.name == %# and (country == %#) and (specific == %#) and (prefix == %#) and (enabled == YES) and ((rateSheet == %#) OR (rateSheet == %#))",
outCarrierName,
countryStr,
specificStr,
outCarrierPrefixStr,
outCarrierRateSheet,
#"Price table"]];
NSArray *destinationWeBuyList = nil;
//[requestDestinationWeBuy includesSubentities];
[requestDestinationWeBuy setResultType:NSManagedObjectIDResultType];
destinationWeBuyList = [moc executeFetchRequest:requestDestinationWeBuy error:&error];
if i didn't match first predicate, i have to cut last digit of code volume (it's a digits and send fetch request again.
int maxCodeDeep = 8;
if ([codeStr length] < maxCodeDeep) maxCodeDeep = [[NSNumber numberWithUnsignedInt:[codeStr length]] intValue] - 1;
NSRange codeStrRange = NSMakeRange(0,[codeStr length]);
NSString *changedCode = [NSString string];
BOOL huntingWasSuccess = NO;
for (NSUInteger codeDeep = 0; codeDeep < maxCodeDeep;codeDeep++)
{
codeStrRange.length = codeStrRange.length - 1;
changedCode = [codeStr substringWithRange:codeStrRange];
NSFetchRequest *compareCode = [[[NSFetchRequest alloc] init] autorelease];
[compareCode setEntity:[NSEntityDescription entityForName:#"CodesvsDestinationsList"
inManagedObjectContext:moc]];
NSString *codeRelationshipName = #"destinationsListWeBuy";
[compareCode setPredicate:[NSPredicate predicateWithFormat:#"(%K.carrier.name == %#) and ((code == %#) OR (originalCode == %#)) and (%K.prefix == %#) and (enabled == YES) and ((rateSheetID == %#) OR (rateSheetID == %#))",codeRelationshipName, outCarrierName,changedCode,changedCode, codeRelationshipName, outCarrierPrefixStr,outCarrierRateSheetID,#"65535"]];
//[compareCode includesSubentities];
//[compareCode includesPropertyValues];
[compareCode setResultType:NSManagedObjectIDResultType];
NSArray *codeAfterComparing = [moc executeFetchRequest:compareCode error:&error];
if ([codeAfterComparing count] == 0) {
NSLog(#"ROUTING: Compare was unsucceseful with parameters:%#",compareCode);
continue;
}
else {
destinationWeBuy = [[moc objectWithID:[codeAfterComparing lastObject]] valueForKey:codeRelationshipName];
NSLog(#"ROUTING: Compare was succeseful with parameters:%#\n and destination object:%#\n Carrier name is %# ",compareCode,destinationWeBuy,carrierName);
//destinationWeBuy = [destinationWeBuyObj objectID];
huntingWasSuccess = YES;
break;
}
}
Unfortunately, this is get a time and processor resources.
Some of latest WWDC recommendations is propose me to using #count, but i don't understand how i can using it in my case.
p.s. important note - i'm using a object, which i find, in next operations and parent object.
Try using subquery to narrow down your search area.Subquery NSExpression

Problem with NSNumber and plotting a graph with Core-Plot

I try to plot a Bar Chart with Core-Plot with an Array (content are NSIntegers) given one view before.
After transfering the Array in an NSInteger, i must convert it into a NSDecimalNumber, and in this process, my NSInteger (for example 45) becomes "60900224"...
Here's the code extract:
-(NSNumber *)numberForPlot:(CPPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index
{ NSInteger *values = [Werte objectAtIndex:index];
NSDecimalNumber *num = nil;
if ( [plot isKindOfClass:[CPBarPlot class]] ) {
switch ( fieldEnum ) {
case CPBarPlotFieldBarLocation:
num = (NSDecimalNumber *)[NSDecimalNumber numberWithUnsignedInteger:index];
break;
case CPBarPlotFieldBarLength:
//num = (NSDecimalNumber *)[NSDecimalNumber numberWithUnsignedInteger:(index+1)*(index+1)];
num = [NSNumber numberWithInt:values];
if ( [plot.identifier isEqual:#"Bar Plot 2"] )
num = [num decimalNumberBySubtracting:[NSDecimalNumber decimalNumberWithString:#"10"]];
break;
}
}
return num;
}
Thanks for help!!
NSInteger is not an object type and can't be stored in an NSArray (which your Werte appears to be). You seem to be implicitly converting from a pointer to an integer.
Instead, you should always put NSNumber objects into the array, and then get NSInteger values out of those via integerValue:
NSInteger value = [[Werte objectAtIndex:index] integerValue];

What kind of category methods do you use to make Cocoa programming easier?

I use a collection of category methods for Cocoa's built in classes to make my life easier. I'll post some examples, but I really want to see what other coders have come up with. What kind of handy category methods are you using?
Example #1:
#implementation NSColor (MyCategories)
+ (NSColor *)colorWithCode:(long)code
{
return [NSColor colorWithCalibratedRed:((code & 0xFF000000) >> 24) / 255.0
green:((code & 0x00FF0000) >> 16) / 255.0
blue:((code & 0x0000FF00) >> 8) / 255.0
alpha:((code & 0x000000FF) ) / 255.0];
}
#end
// usage:
NSColor * someColor = [NSColor colorWithCode:0xABCDEFFF];
Example #2:
#implementation NSView (MyCategories)
- (id)addNewSubViewOfType:(Class)viewType inFrame:(NSRect)frame
{
id newView = [[viewType alloc] initWithFrame:frame];
[self addSubview:newView];
return [newView autorelease];
}
#end
// usage:
NSButton * myButton = [someView addNewSubviewOfType:[NSButton class]
inFrame:someRect];
I've really been loving Andy Matuschak's "KVO+Blocks" category on NSObject. (Yes, it adds some new classes internally as implementation details, but the end result is just a category on NSObject). It lets you provide a block to be executed when a KVO-conforming value changes rather than having to handle every KVO observation in the observeValueForKeyPath:ofObject:change:context: method.
Regular Expressions with RegexKitLite. Download # RegexKitLite-3.1.tar.bz2
Category, which adds md5/sha1 hashing to NSString. NSData one is similar.
#define COMMON_DIGEST_FOR_OPENSSL
#import <CommonCrypto/CommonDigest.h>
#implementation NSString(GNExtensions)
- (NSString*)
hashMD5
{
NSData* data = [self dataUsingEncoding: NSUTF8StringEncoding allowLossyConversion: NO];
unsigned char hashingBuffer[16];
char outputBuffer[32];
CC_MD5([data bytes], [data length], hashingBuffer);
for(int index = 0; index < 16; index++)
{
sprintf(&outputBuffer[2 * index], "%02x", hashingBuffer[index]);
}
return([NSString stringWithCString: outputBuffer length: 32]);
}
- (NSString*)
hashSHA1
{
NSData* data = [self dataUsingEncoding: NSUTF8StringEncoding allowLossyConversion: NO];
unsigned char hashingBuffer[20];
char outputBuffer[40];
CC_SHA1([data bytes], [data length], hashingBuffer);
for(int index = 0; index < 20; index++)
{
sprintf(&outputBuffer[2 * index], "%02x", hashingBuffer[index]);
}
return([NSString stringWithCString: outputBuffer length: 40]);
}
#end
I have a few nifty methods on NSDate. This is self-explanatory:
-(BOOL)isOnTheSameDayAsDate:(NSDate *)date {
NSCalendar *cal = [NSCalendar currentCalendar];
NSDateComponents *selfComponents = [cal components:NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit
fromDate:self];
NSDateComponents *dateComponents = [cal components:NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit
fromDate:date];
return (([selfComponents day] == [dateComponents day]) &&
([selfComponents month] == [dateComponents month]) &&
([selfComponents year] == [dateComponents year]));
}
Usage:
if ([aDate isOnTheSameDayAsDate:anotherDate]) { ... }
This provides a method to easily get dates like "9am the day before":
-(NSDate *)dateWithDayDelta:(NSInteger)daysBeforeOrAfter atHour:(NSUInteger)hour minute:(NSUInteger)minute second:(NSUInteger)second {
NSDate *date = [self addTimeInterval:(24 * 60 * 60) * daysBeforeOrAfter];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *comps = [calendar components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit |
NSMinuteCalendarUnit | NSSecondCalendarUnit
fromDate:date];
[comps setHour:hour];
[comps setMinute:minute];
[comps setSecond:second];
return [calendar dateFromComponents:comps];
}
Usage:
// We want 9am yesterday
NSDate *nineAmYesterday = [[NSDate date] dateWithDayDelta:-1
atHour:9
minute:0
second:0];

Resources