Простой вопрос NSTextList - PullRequest
       1

Простой вопрос NSTextList

3 голосов
/ 23 августа 2011

Я пытаюсь использовать NSTextList для отображения числового списка в несколько строк NSTextField, но он не работает должным образом.

Используемый пример кода:

- (IBAction)displayResult:(id)sender
{
    NSTextList *list = [[NSTextList alloc] initWithMarkerFormat:self.markerFormat options:1]; // {Decimal} passed as marker format
    NSMutableParagraphStyle *paragraph = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
    [paragraph setTextLists:[NSArray arrayWithObject:list]];
    [list release];
    NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:paragraph, NSParagraphStyleAttributeName, nil];
    NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:self.inputString attributes:attributes] ; // input string is- George \n Thomas \n Ashok
    [self setOutputString:attrString]; 
    [attrString release];
    [paragraph release];
}

Ввод -

George 

Thomas 

Ashok

Вывод должен быть -

1 George

2 Thomas

3 Ashok

, но вывод, который он показывает - -

George 

Thomas 

Ashok

Может кто-нибудь подсказать, какдобиться ожидаемого выхода?

Ответы [ 2 ]

6 голосов
/ 26 июня 2013

Для меня все, что вы делаете, выглядит прекрасно и богато :) Есть проблема с вашей строкой ввода Попробуйте это,

NSTextList *list1 = [[NSTextList alloc] initWithMarkerFormat:@"{decimal}" options:0]; // {Decimal} passed as marker format
NSMutableParagraphStyle *paragraph = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
[list1 setStartingItemNumber:1];
[paragraph setTextLists:[NSArray arrayWithObject:list1]];

NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:paragraph, NSParagraphStyleAttributeName, nil];
NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"\t%@ Suhas \n \t%@ Devarshi \n \t%@ Rohith\n", [list1 markerForItemNumber:1],[list1 markerForItemNumber:2],[list1 markerForItemNumber:3]] attributes:attributes] ;
 [self.text setStringValue:attrString];//self.text is a NSTextField instance. kindly ignore the compiler warning:)
2 голосов
/ 20 мая 2016

Я знаю, что это на четыре года позже, но я недавно столкнулся с той же проблемой и смог решить ее с помощью Swift.

Я хотел иметь возможность преобразовать выделенный текст в NSTextView в маркированный список, но выбор может явно охватывать части нескольких абзацев.Первым шагом является выяснение правильного диапазона выбора путем доступа к NSTextView.rangeForUserParagraphAttributeChange, который гарантирует, что вы всегда будете выбирать диапазон, включающий полные абзацы, а не частичные.

Теперь более сложная часть:Вы должны найти каждый абзац внутри измененного диапазона выделения и добавить к нему маркер, а также добавить соответствующий объект текстового списка и заменить текст в измененном выбранном диапазоне, чтобы включить новый текст.Это легче сказать, чем сделать, и мне понадобилось несколько дней, чтобы понять (я все еще учусь в колледже, так что пойди разберись).

Я не смог ничего найти об этом в ИнтернетеНадеюсь, это избавит будущих интернет-путешественников от проблем, с которыми мне пришлось столкнуться.

if let range = textView?.rangeForUserParagraphAttributeChange {
// So, the user has selected some text. Range may or may not be the user's exact selection...
// The start of range has possibly back-tracked from the start of the selection to the start of
// the nearest paragraph, and the end has possibly extended from the end of the selection to the
// end of the nearest paragraph at that point.
// Therefore, we are guarunteed to be selecting complete paragraphs.
//
// Now, for each paragraph, we want to insert a bullet.
// The trick is finding the range of each paragraph.
//
// Find the attributed string contents of the entire possibly multi-paragraph selection:
let entireRangeText = textView!.textStorage!.attributedSubstringFromRange(range)
// Find the string contents
let entireRangeString = entireRangeText.string as NSString

// Let's make a list to store all of the paragraph ranges inside range
var paragraphRanges: [NSRange] = []

// Find the range of the first paragraph (possibly the only paragraph)
var paraRange = entireRangeString.paragraphRangeForRange(NSMakeRange(0, 0))
// Para range is relative to range, so let's keep track of it's actual position.
var actualRange = NSMakeRange(paraRange.location + range.location, paraRange.length)
// Add it to the list
paragraphRanges += [actualRange]

// Now find each paragraph inside the selection
while NSMaxRange(paraRange) < entireRangeString.length {
    // Find the next range relative to the range
    paraRange = entireRangeString.paragraphRangeForRange(NSMakeRange(NSMaxRange(paraRange), 0))
    // Find it's actual range relative to the entire text
    actualRange = NSMakeRange(paraRange.location + range.location, paraRange.length)
    // Add it to our list of paragraph ranges
    paragraphRanges += [actualRange]
}

// This is the attributed string that we will use to replace the entireRangeText
// with the bulleted version.
let newText = NSMutableAttributedString()

// Start counting our bullets at 1...
// Todo: Respect the starting number in the preferences
var bulletNumber = 1

// Make a list object to add to each paragraph
// Todo: Respect the list type specified
let list = NSTextList(markerFormat: "{decimal}", options: 0)

// Go through each paragraph range and add bullets to the text inside it
for paragraphRange in paragraphRanges {
    // Construct the bullet header:
    let bulletText = "\t" + list.markerForItemNumber(bulletNumber) + "\t"
    // Find the text from the paragraph
    let paragraphText = textView!.textStorage!.attributedSubstringFromRange(paragraphRange)
    let mutableParagraphText = NSMutableAttributedString(attributedString: paragraphText)

    // A range pointer we really don't need:
    var effectiveRange = NSRange()

    // Construct our new string appropriately
    // Get the paragraph attribute and modify it to have the text list
    if let paragraphStyle = paragraphText.attribute(NSParagraphStyleAttributeName,
                                                    atIndex: 0,
                                                    longestEffectiveRange: &effectiveRange,
                                                    inRange: NSMakeRange(0, paragraphText.length))
        as? NSParagraphStyle {
        let newParagraphStyle = paragraphStyle.mutableCopy() as! NSMutableParagraphStyle
        // Attach the list object to the paragraph style of the paragraph text
        // So that auto list continuation will work properly
        newParagraphStyle.textLists = [list]
        // Update the text's paragraph style:
        mutableParagraphText.addAttributes([NSParagraphStyleAttributeName: newParagraphStyle],
                                            range: NSMakeRange(0, paragraphText.length))
    }

    // Make the bullet's attributes match the attributes of the text it's near, just
    // like TextEdit does.
    newText.appendAttributedString(
        NSAttributedString(string: bulletText,
            attributes: mutableParagraphText.attributesAtIndex(0,
                longestEffectiveRange: &effectiveRange,
                inRange: NSMakeRange(0, paragraphText.length))))
    newText.appendAttributedString(mutableParagraphText)

    // Increase to the next bullet number:
    bulletNumber += 1
}

// Finally, insert our string
textView?.shouldChangeTextInRange(range, replacementString: nil)
textView?.insertText(newText, replacementRange: range)

// Tell the undo manager what happened:
textView?.didChangeText()
undoManager?.setActionName("Paragraph List") // ToDo: Localize

// Change the selection for auto-insertion to work
// IMPORTANT: Note that you have to change the selection twice to get auto list insertion to work
// (at least on my system). Must be a bug.
textView?.setSelectedRange(NSMakeRange(range.location + newText.string.characters.count - 1, 0))
textView?.setSelectedRange(NSMakeRange(range.location + newText.string.characters.count, 0))
}
...