NSTextFieldCell вертикальное выравнивание, решения, кажется, подавляют горизонтальное выравнивание - PullRequest
9 голосов
/ 19 ноября 2009

У меня есть NSTextFieldCell, который я хочу отображать со средним вертикальным выравниванием. Благодаря старому вопросу и записи в блоге у меня есть два рабочих решения.

Однако оба решения, похоже, ограничивают мою способность устанавливать ячейку как выровненную по правому краю. Может ли кто-нибудь помочь мне сделать так, чтобы одно из этих решений поддерживало обе формы выравнивания?

Вот код для одного решения:

@implementation MiddleAlignedTextFieldCell

- (NSRect)titleRectForBounds:(NSRect)theRect {
    NSRect titleFrame = [super titleRectForBounds:theRect];
    NSSize titleSize = [[self attributedStringValue] size];
    titleFrame.origin.y = theRect.origin.y - .5 + (theRect.size.height - titleSize.height) / 2.0;
    return titleFrame;
}

- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView {
    NSRect titleRect = [self titleRectForBounds:cellFrame];
    [[self attributedStringValue] drawInRect:titleRect];
}

@end

Альтернативное решение (получено из этого блога ):

@implementation RSVerticallyCenteredTextFieldCell

- (NSRect)drawingRectForBounds:(NSRect)theRect
{
    NSRect newRect = [super drawingRectForBounds:theRect];

    if (mIsEditingOrSelecting == NO)
    {
        // Get our ideal size for current text
        NSSize textSize = [self cellSizeForBounds:theRect];

        // Center that in the proposed rect
        float heightDelta = newRect.size.height - textSize.height;  
        if (heightDelta > 0)
        {
            newRect.size.height -= heightDelta;
            newRect.origin.y += (heightDelta / 2);
        }
    }

    return newRect;
}

- (void)selectWithFrame:(NSRect)aRect inView:(NSView *)controlView editor:(NSText *)textObj delegate:(id)anObject start:(int)selStart length:(int)selLength
{
    aRect = [self drawingRectForBounds:aRect];
    mIsEditingOrSelecting = YES;    
    [super selectWithFrame:aRect inView:controlView editor:textObj delegate:anObject start:selStart length:selLength];
    mIsEditingOrSelecting = NO;
}

- (void)editWithFrame:(NSRect)aRect inView:(NSView *)controlView editor:(NSText *)textObj delegate:(id)anObject event:(NSEvent *)theEvent
{   
    aRect = [self drawingRectForBounds:aRect];
    mIsEditingOrSelecting = YES;
    [super editWithFrame:aRect inView:controlView editor:textObj delegate:anObject event:theEvent];
    mIsEditingOrSelecting = NO;
}

@end

Ответы [ 3 ]

5 голосов
/ 19 ноября 2009

Я отправляю этот ответ на вопрос, поскольку он работает, однако я нахожу тот факт, что я не смог найти другой способ проверить настройку выравнивания из IB, очень раздражает. Доступ к _cFlags кажется немного грязным, и я бы хотел найти более чистый метод.

На основе кода, опубликованного ранее этой записи в блоге .

- (NSRect)drawingRectForBounds:(NSRect)theRect
{
    // Get the parent's idea of where we should draw
    NSRect newRect = [super drawingRectForBounds:theRect];

    if (mIsEditingOrSelecting == NO)
    {
        // Get our ideal size for current text
        NSSize textSize = [self cellSizeForBounds:theRect];

        // Center that in the proposed rect
        float heightDelta = newRect.size.height - textSize.height;  
        if (heightDelta > 0)
        {
            newRect.size.height -= heightDelta;
            newRect.origin.y += (heightDelta / 2);
        }

        // For some reason right aligned text doesn't work.  This section makes it work if set in IB.
        // HACK: using _cFlags isn't a great idea, but I couldn't find another way to find the alignment.
        // TODO: replace _cFlags usage if a better solution is found.
        float widthDelta = newRect.size.width - textSize.width;
        if (_cFlags.alignment == NSRightTextAlignment && widthDelta > 0) {
            newRect.size.width -= widthDelta;
            newRect.origin.x += widthDelta;
        }

    }

    return newRect;
}
3 голосов
/ 19 ноября 2009

Вы можете использовать NSParagraphStyle / NSMutableParagraphStyle, чтобы установить выравнивание (и другие атрибуты). Добавьте соответствующим образом настроенный объект NSParagraphStyle к полному диапазону вашей атрибутированной строки.

2 голосов
/ 19 ноября 2009

Есть пара потенциальных решений, опубликованных в подобном вопросе , который я задал некоторое время назад.

Честно говоря, я все еще использую недокументированный логический _cFlags.vCentered ( tsk tsk , плохой программист!), Чтобы выполнить свою работу. Все просто и работает. Я изобрету колесо позже, если придется.

Обновление:

ОК, думаю, я понял это. Оба решения полагаются на вызов super для получения прямоугольника по умолчанию, а затем изменяют origin.y и size.height для выполнения вертикального центрирования. Однако вызовы super возвращают прямоугольник, ширина которого уже была отрегулирована для размещения текста по горизонтали.

Решение состоит в том, чтобы использовать origin.x и size.width из прямоугольника границ, который передается методу:

В растворе № 1:

- (NSRect)titleRectForBounds:(NSRect)theRect {
    NSRect titleFrame = [super titleRectForBounds:theRect];
    NSSize titleSize = [[self attributedStringValue] size];

    // modified:
    theRect.origin.y += (theRect.size.height - titleSize.height)/2.0 - 0.5;
    return theRect;
}

В растворе № 2:

- (NSRect)drawingRectForBounds:(NSRect)theRect
{
    NSRect newRect = [super drawingRectForBounds:theRect];

    // modified:
    newRect.origin.x = theRect.origin.x;
    newRect.size.width = theRect.size.width;

    if (mIsEditingOrSelecting == NO)
    {
        // Get our ideal size for current text
        NSSize textSize = [self cellSizeForBounds:theRect];

        // Center that in the proposed rect
        float heightDelta = newRect.size.height - textSize.height;  
        if (heightDelta > 0)
        {
            newRect.size.height -= heightDelta;
            newRect.origin.y += (heightDelta / 2);
        }
    }

    return newRect;
}
...