Точное соответствие фону выбранного NSMenuItem

Я создаю собственное представление для файла NSMenuItem. Чтобы нарисовать фон при выборе, я адаптировал пару строк из CustomMenus. Образец CustomMenus имеет:

    [[NSColor alternateSelectedControlColor] set];
    NSRectFillUsingOperation(dirtyRect, NSCompositeSourceOver);

.. и я использую selectedMenuItemColor, потому что alterSelectedControlColor был сплошным цветом и выглядел не очень хорошо:

    [[NSColor selectedMenuItemColor] set];
    NSRectFillUsingOperation(dirtyRect, NSCompositeSourceOver);

Использование selectedMenuItemColor лучше, но это все же не совсем то же самое, что и реальный выбранный NSMenuItem.

Вот снимок экрана, показывающий реальный выбранный фон NSMenuItem слева и selectedMenuItemColor справа в «синем» виде:

Прямое сравнение реального фона выбранного пункта меню и выбранногоMenuItemColor в синем виде

Вы можете видеть, что есть дополнительное полупрозрачное наложение белого градиента на реальный выбранный фон NSMenuItem.

Как воспроизвести реальный выбранный фон NSMenuItem?

EDIT: Это для Mac OS 10.9.5.

EDIT2: вот сравнение внешнего вида "Graphite":

Прямое сравнение реального фона выбранного пункта меню и выбранногоMenuItemColor во внешнем виде Graphite


person Daniel Trebbien    schedule 21.09.2014    source источник
comment
Вы имеете в виду pearlescent. :-)   -  person markhunte    schedule 22.09.2014


Ответы (2)


Путем проб и ошибок я пришел к следующему коду, который рисует фон, почти неотличимый от реального выбранного фона NSMenuItem как в «Синем», так и в «Графитовом» виде:

    [[NSColor selectedMenuItemColor] set];
    NSRectFillUsingOperation(dirtyRect, NSCompositeSourceOver);

    if (dirtyRect.size.height > 1) {
        const NSControlTint currentControlTint = [NSColor currentControlTint];

        const CGFloat startingOpacity = (NSBlueControlTint == currentControlTint ? (CGFloat)0.16 : (CGFloat)0.09);
        NSGradient *grad = [[NSGradient alloc] initWithStartingColor:[NSColor colorWithWhite:(CGFloat)1.0 alpha:startingOpacity] endingColor:[NSColor colorWithWhite:(CGFloat)1.0 alpha:(CGFloat)0.0]];

        const CGFloat heightMinus1 = (CGFloat)(dirtyRect.size.height - 1);
        [grad drawFromPoint:NSMakePoint(dirtyRect.origin.x, dirtyRect.origin.y + heightMinus1) toPoint:NSMakePoint(dirtyRect.origin.x, dirtyRect.origin.y + 1) options:0u];

        if (NSBlueControlTint == currentControlTint) {
            [[NSColor colorWithWhite:(CGFloat)1.0 alpha:(CGFloat)0.1] set];
            NSRectFillUsingOperation(NSMakeRect(dirtyRect.origin.x, dirtyRect.origin.y + heightMinus1, dirtyRect.size.width, (CGFloat)1.0), NSCompositeSourceOver);
        }
    }

Вот параллельные сравнения:

Сравнение внешнего вида цвета морской волны

Сравнение внешнего вида графита

Левые половины (80 пикселей) двух изображений показывают реальный выбранный фон NSMenuItem, а правые половины двух изображений являются результатом кода.

person Daniel Trebbien    schedule 22.09.2014
comment
Выглядит неплохо. Но имейте в виду, что 10.10 будет намного сложнее с темным режимом, изменениями яркости и специальных возможностей. - person uchuugaka; 23.09.2014
comment
Просто хотел добавить быстрое примечание, что это похоже на регрессию - OS X 10.6 рисует правильный градиент для -[NSColor selectedMenuItemColor]. Я не уверен, когда он сломался, но у меня такое же поведение, как и у вас в OS X 10.9. - person AriX; 09.11.2014
comment
Я преобразовал ваш код в Swift: gist.github.com/joelcox/28de2f0cb21ea47bd789 - person joelcox; 23.09.2015

Это не полупрозрачный белый градиент. Он рисует градиент. Для этого используйте NSGradient и NSBezierPath для рисования. Обратите внимание, что вам также нужно придерживаться того, что предпочитает пользователь. Серый или цвет морской волны. Это изменяет выделение меню. Кроме того, вам нужно быть готовым сделать это по-другому в 10.10.

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

person uchuugaka    schedule 21.09.2014