候選窗格:美化 Voltaire 選字窗的美術風格。

- 之前的設計的審美是 macOS 10.5 Leopard 時代的,從 macOS 10.7 開始掉渣。由於威注音的最低系統需求早已至 macOS 10.12 Sierra,故盡量利用現代 macOS 系統的 Cocoa 桌面美術特性。
This commit is contained in:
ShikiSuen 2022-01-10 18:27:05 +08:00
parent 2935819d42
commit 317dcc3848
4 changed files with 121 additions and 55 deletions

View File

@ -55,10 +55,12 @@
NSRect contentRect = NSMakeRect(128.0, 128.0, 0.0, 0.0);
NSUInteger styleMask = NSBorderlessWindowMask | NSNonactivatingPanelMask;
NSPanel *panel = [[NSPanel alloc] initWithContentRect:contentRect styleMask:styleMask backing:NSBackingStoreBuffered defer:NO];
NSWindow *panel = [[NSWindow alloc] initWithContentRect:contentRect styleMask:styleMask backing:NSBackingStoreBuffered defer:NO];
[panel setLevel:kCGPopUpMenuWindowLevel];
[panel setHasShadow:YES];
[panel setOpaque:NO];
[panel setBackgroundColor:[NSColor clearColor]];
self = [self initWithWindow:panel];
if (self) {
contentRect.origin = NSMakePoint(0.0, 0.0);
@ -67,20 +69,30 @@
_candidateView.action = @selector(candidateViewMouseDidClick:);
[[panel contentView] addSubview:_candidateView];
contentRect.size = NSMakeSize(36.0, 20.0);
contentRect.size = NSMakeSize(16.0, 20.0);
_nextPageButton = [[NSButton alloc] initWithFrame:contentRect];
_prevPageButton = [[NSButton alloc] initWithFrame:contentRect];
[_nextPageButton setButtonType:NSMomentaryLightButton];
[_nextPageButton setBezelStyle:NSSmallSquareBezelStyle];
[_nextPageButton setTitle:@"»"];
[_nextPageButton setBezelStyle:NSBezelStyleSmallSquare];
[_nextPageButton setTitle:@""];
[_nextPageButton setTarget:self];
[_nextPageButton setAction:@selector(pageButtonAction:)];
[_nextPageButton setWantsLayer: YES];
[_nextPageButton.layer setCornerRadius: 3];
[_nextPageButton.layer setBorderColor: [NSColor clearColor].CGColor];
[_nextPageButton.layer setBorderWidth: 3];
[_nextPageButton.layer setBackgroundColor: [NSColor windowBackgroundColor].CGColor];
[_prevPageButton setButtonType:NSMomentaryLightButton];
[_prevPageButton setBezelStyle:NSSmallSquareBezelStyle];
[_prevPageButton setTitle:@"«"];
[_prevPageButton setBezelStyle:NSBezelStyleSmallSquare];
[_prevPageButton setTitle:@""];
[_prevPageButton setTarget:self];
[_prevPageButton setAction:@selector(pageButtonAction:)];
[_prevPageButton setWantsLayer: YES];
[_prevPageButton.layer setCornerRadius: 3];
[_prevPageButton.layer setBorderColor: [NSColor clearColor].CGColor];
[_prevPageButton.layer setBorderWidth: 3];
[_prevPageButton.layer setBackgroundColor: [NSColor windowBackgroundColor].CGColor];
[[panel contentView] addSubview:_nextPageButton];
[[panel contentView] addSubview:_prevPageButton];

View File

@ -42,6 +42,11 @@ NS_INLINE CGFloat max(CGFloat a, CGFloat b) { return a > b ? a : b; }
@synthesize action = _action;
@synthesize target = _target;
static NSColor *colorFromRGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
{
return [NSColor colorWithDeviceRed:(r/255.0f) green:(g/255.0f) blue:(b/255.0f) alpha:(a/255.0f)];
}
- (void)dealloc
{
_keyLabels = nil;
@ -74,18 +79,20 @@ NS_INLINE CGFloat max(CGFloat a, CGFloat b) { return a > b ? a : b; }
- (void)setKeyLabelFont:(NSFont *)labelFont candidateFont:(NSFont *)candidateFont
{
NSColor *clrCandidateText = colorFromRGBA(233,233,233,255);
NSColor *clrCandidateTextIndex = colorFromRGBA(233,233,233,213);
NSMutableParagraphStyle *paraStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
[paraStyle setAlignment:NSCenterTextAlignment];
_keyLabelAttrDict = [NSDictionary dictionaryWithObjectsAndKeys:
labelFont, NSFontAttributeName,
paraStyle, NSParagraphStyleAttributeName,
[NSColor blackColor], NSForegroundColorAttributeName,
clrCandidateTextIndex, NSForegroundColorAttributeName,
nil];
_candidateAttrDict = [NSDictionary dictionaryWithObjectsAndKeys:
candidateFont, NSFontAttributeName,
paraStyle, NSParagraphStyleAttributeName,
[NSColor textColor], NSForegroundColorAttributeName,
clrCandidateText, NSForegroundColorAttributeName,
nil];
CGFloat labelFontSize = [labelFont pointSize];
@ -120,17 +127,21 @@ NS_INLINE CGFloat max(CGFloat a, CGFloat b) { return a > b ? a : b; }
- (void)drawRect:(NSRect)dirtyRect
{
NSColor *backgroundColor = [NSColor controlBackgroundColor];
NSColor *darkGray = [NSColor colorWithDeviceWhite:0.7 alpha:1.0];
NSColor *lightGray = [NSColor colorWithDeviceWhite:0.8 alpha:1.0];
NSColor *clrCandidateSelectedBG = [NSColor alternateSelectedControlColor];
NSColor *clrCandidateSelectedText = colorFromRGBA(233,233,233,255);
NSColor *clrCandidateWindowBorder = colorFromRGBA(255,255,255,75);
NSColor *clrCandidateWindowBG = colorFromRGBA(28,28,28,255);
NSColor *clrCandidateBG = colorFromRGBA(28,28,28,255);
[self setWantsLayer: YES];
[self.layer setBorderColor: [clrCandidateWindowBorder CGColor]];
[self.layer setBorderWidth: 1];
[self.layer setCornerRadius: 6];
NSRect bounds = [self bounds];
[backgroundColor setFill];
[clrCandidateWindowBG setFill];
[NSBezierPath fillRect:bounds];
[[NSColor darkGrayColor] setStroke];
[NSBezierPath strokeLineFromPoint:NSMakePoint(bounds.size.width, 0.0) toPoint:NSMakePoint(bounds.size.width, bounds.size.height)];
NSUInteger count = [_elementWidths count];
CGFloat accuWidth = 0.0;
@ -138,27 +149,26 @@ NS_INLINE CGFloat max(CGFloat a, CGFloat b) { return a > b ? a : b; }
for (NSUInteger index = 0; index < count; index++) {
NSDictionary *activeCandidateAttr = _candidateAttrDict;
CGFloat currentWidth = [[_elementWidths objectAtIndex:index] doubleValue];
NSRect labelRect = NSMakeRect(accuWidth, 0.0, currentWidth, _keyLabelHeight);
NSRect candidateRect = NSMakeRect(accuWidth, _keyLabelHeight + 1.0, currentWidth, _candidateTextHeight);
NSRect labelRect = NSMakeRect(accuWidth, 0.0, currentWidth + 1.0, _keyLabelHeight + 1.0);
NSRect candidateRect = NSMakeRect(accuWidth, _keyLabelHeight + 1.0, currentWidth + 1.0, _candidateTextHeight);
if (index == _highlightedIndex) {
[darkGray setFill];
[clrCandidateSelectedBG setFill];
}
else {
[lightGray setFill];
[clrCandidateBG setFill];
}
[NSBezierPath fillRect:labelRect];
[[_keyLabels objectAtIndex:index] drawInRect:labelRect withAttributes:_keyLabelAttrDict];
if (index == _highlightedIndex) {
[[NSColor selectedTextBackgroundColor] setFill];
[clrCandidateSelectedBG setFill];
activeCandidateAttr = [_candidateAttrDict mutableCopy];
[(NSMutableDictionary *)activeCandidateAttr setObject:[NSColor selectedTextColor] forKey:NSForegroundColorAttributeName];
[(NSMutableDictionary *)activeCandidateAttr setObject:clrCandidateSelectedText forKey:NSForegroundColorAttributeName];
}
else {
[backgroundColor setFill];
[clrCandidateBG setFill];
}
[NSBezierPath fillRect:candidateRect];
@ -186,8 +196,7 @@ NS_INLINE CGFloat max(CGFloat a, CGFloat b) { return a > b ? a : b; }
result = index;
break;
}
accuWidth += currentWidth + 1.0;
accuWidth += currentWidth;
}
return result;

View File

@ -1,7 +1,12 @@
//
// VTVerticalCandidateController.m
//
// Copyright (c) 2012 Lukhnos D. Liu (http://lukhnos.org)
// Copyright (c) 2021-2022 The vChewing Project.
// Copyright (c) 2011-2022 The OpenVanilla Project.
//
// Contributors:
// Lukhnos Liu (@lukhnos) @ OpenVanilla
// Shiki Suen (ShikiSuen) @ vChewing
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -36,7 +41,12 @@ NS_INLINE CGFloat max(CGFloat a, CGFloat b) { return a > b ? a : b; }
static const CGFloat kCandidateTextPadding = 24.0;
static const CGFloat kCandidateTextLeftMargin = 8.0;
#if defined(__MAC_10_16)
static NSColor *colorFromRGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
{
return [NSColor colorWithDeviceRed:(r/255.0f) green:(g/255.0f) blue:(b/255.0f) alpha:(a/255.0f)];
}
#if defined(__MAC_11_0)
static const CGFloat kCandidateTextPaddingWithMandatedTableViewPadding = 18.0;
static const CGFloat kCandidateTextLeftMarginWithMandatedTableViewPadding = 0.0;
#endif
@ -60,29 +70,50 @@ static const CGFloat kCandidateTextLeftMarginWithMandatedTableViewPadding = 0.0;
- (id)init
{
NSRect contentRect = NSMakeRect(128.0, 128.0, 0.0, 0.0);
NSUInteger styleMask = NSBorderlessWindowMask | NSNonactivatingPanelMask;
NSPanel *panel = [[NSPanel alloc] initWithContentRect:contentRect styleMask:styleMask backing:NSBackingStoreBuffered defer:NO];
[panel setLevel:kCGPopUpMenuWindowLevel];
[panel setHasShadow:YES];
// NSColor *clrCandidateSelectedBG = [NSColor systemBlueColor];
NSColor *clrCandidateSelectedText = [[NSColor whiteColor] colorWithAlphaComponent: 0.8];
NSColor *clrCandidateWindowBorder = colorFromRGBA(255,255,255,75);
NSColor *clrCandidateWindowBG = colorFromRGBA(28,28,28,255);
// NSColor *clrCandidateBG = colorFromRGBA(28,28,28,255);
self = [self initWithWindow:panel];
NSRect contentRect = NSMakeRect(128.0, 128.0, 0.0, 0.0);
NSUInteger styleMask = NSBorderlessWindowMask | NSNonactivatingPanelMask;
NSView *panelView = [[NSView alloc] initWithFrame:contentRect];
NSWindow *panel = [[NSWindow alloc] initWithContentRect:contentRect styleMask:styleMask backing:NSBackingStoreBuffered defer:NO];
[panel setLevel:kCGPopUpMenuWindowLevel];
[panel setContentView: panelView];
[panel setHasShadow:YES];
[panel setOpaque:NO];
[panel setBackgroundColor: [NSColor clearColor]];
[panel setOpaque:false];
[panelView setWantsLayer: YES];
[panelView.layer setBorderColor: [clrCandidateWindowBorder CGColor]];
[panelView.layer setBorderWidth: 1];
[panelView.layer setCornerRadius: 6];
[panelView.layer setBackgroundColor: [clrCandidateWindowBG CGColor]];
self = [self initWithWindow:panel];
if (self) {
contentRect.origin = NSMakePoint(0.0, 0.0);
NSRect stripRect = contentRect;
stripRect.size.width = 10.0;
_keyLabelStripView = [[VTVerticalKeyLabelStripView alloc] initWithFrame:stripRect];
[_keyLabelStripView setWantsLayer: YES];
[_keyLabelStripView.layer setBorderWidth: 0];
[[panel contentView] addSubview:_keyLabelStripView];
NSRect scrollViewRect = contentRect;
scrollViewRect.origin.x = stripRect.size.width;
scrollViewRect.size.width -= stripRect.size.width;
scrollViewRect.size.width -= stripRect.size.width;
_scrollView = [[NSScrollView alloc] initWithFrame:scrollViewRect];
[_scrollView setAutohidesScrollers: YES];
[_scrollView setWantsLayer: YES];
[_scrollView.layer setBorderWidth: 0];
[_scrollView setDrawsBackground:NO];
// >=10.7 only, elastic scroll causes some drawing issues with visible scroller, so we disable it
if ([_scrollView respondsToSelector:@selector(setVerticalScrollElasticity:)]) {
[_scrollView setVerticalScrollElasticity:NSScrollElasticityNone];
@ -95,6 +126,8 @@ static const CGFloat kCandidateTextLeftMarginWithMandatedTableViewPadding = 0.0;
NSTableColumn *column = [[NSTableColumn alloc] initWithIdentifier:@"candidate"];
[column setDataCell:[[NSTextFieldCell alloc] init]];
[column setEditable:NO];
[column.dataCell setTextColor: clrCandidateSelectedText];
// [column.dataCell setSelectionColor: clrCandidateSelectedBG];
_candidateTextPadding = kCandidateTextPadding;
_candidateTextLeftMargin = kCandidateTextLeftMargin;
@ -106,9 +139,11 @@ static const CGFloat kCandidateTextLeftMarginWithMandatedTableViewPadding = 0.0;
[_tableView setAllowsEmptySelection:YES];
[_tableView setDoubleAction:@selector(rowDoubleClicked:)];
[_tableView setTarget:self];
[_tableView setBackgroundColor:[NSColor clearColor]];
[_tableView setGridColor:[NSColor clearColor]];
#if defined(__MAC_10_16)
if (@available(macOS 10.16, *)) {
#if defined(__MAC_11_0)
if (@available(macOS 11.0, *)) {
[_tableView setStyle:NSTableViewStyleFullWidth];
_candidateTextPadding = kCandidateTextPaddingWithMandatedTableViewPadding;
_candidateTextLeftMargin = kCandidateTextLeftMarginWithMandatedTableViewPadding;
@ -394,8 +429,8 @@ static const CGFloat kCandidateTextLeftMarginWithMandatedTableViewPadding = 0.0;
NSScroller *verticalScroller = [_scrollView verticalScroller];
[verticalScroller setControlSize:controlSize];
[verticalScroller setScrollerStyle:NSScrollerStyleLegacy];
scrollerWidth = [NSScroller scrollerWidthForControlSize:controlSize scrollerStyle:NSScrollerStyleLegacy];
[verticalScroller setScrollerStyle:NSScrollerStyleOverlay];
scrollerWidth = [NSScroller scrollerWidthForControlSize:controlSize scrollerStyle:NSScrollerStyleOverlay];
}
_keyLabelStripView.keyLabelFont = _keyLabelFont;
@ -416,9 +451,9 @@ static const CGFloat kCandidateTextLeftMarginWithMandatedTableViewPadding = 0.0;
}
CGFloat rowSpacing = [_tableView intercellSpacing].height;
CGFloat stripWidth = ceil(maxKeyLabelWidth * 1.20);
CGFloat stripWidth = ceil(maxKeyLabelWidth);
CGFloat tableViewStartWidth = ceil(_maxCandidateAttrStringWidth + scrollerWidth);;
CGFloat windowWidth = stripWidth + 1.0 + tableViewStartWidth;
CGFloat windowWidth = stripWidth + tableViewStartWidth;
CGFloat windowHeight = keyLabelCount * (rowHeight + rowSpacing);
NSRect frameRect = [[self window] frame];
@ -428,7 +463,7 @@ static const CGFloat kCandidateTextLeftMarginWithMandatedTableViewPadding = 0.0;
frameRect.origin = NSMakePoint(topLeftPoint.x, topLeftPoint.y - frameRect.size.height);
[_keyLabelStripView setFrame:NSMakeRect(0.0, 0.0, stripWidth, windowHeight)];
[_scrollView setFrame:NSMakeRect(stripWidth + 1.0, 0.0, tableViewStartWidth, windowHeight)];
[_scrollView setFrame:NSMakeRect(stripWidth, 0.0, tableViewStartWidth, windowHeight)];
[[self window] setFrame:frameRect display:NO];
}
@end

View File

@ -1,7 +1,12 @@
//
// VTVerticalKeyLabelStripView.h
//
// Copyright (c) 2012 Lukhnos D. Liu (http://lukhnos.org)
// Copyright (c) 2021-2022 The vChewing Project.
// Copyright (c) 2011-2022 The OpenVanilla Project.
//
// Contributors:
// Lukhnos Liu (@lukhnos) @ OpenVanilla
// Shiki Suen (ShikiSuen) @ vChewing
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -33,6 +38,11 @@
@synthesize keyLabels = _keyLabels;
@synthesize highlightedIndex = _highlightedIndex;
static NSColor *colorFromRGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
{
return [NSColor colorWithDeviceRed:(r/255.0f) green:(g/255.0f) blue:(b/255.0f) alpha:(a/255.0f)];
}
- (void)dealloc
{
_keyLabelFont = nil;
@ -57,7 +67,7 @@
- (void)drawRect:(NSRect)dirtyRect
{
NSRect bounds = [self bounds];
[[NSColor whiteColor] setFill];
[[NSColor clearColor] setFill];
[NSBezierPath fillRect:bounds];
NSUInteger count = [_keyLabels count];
@ -66,22 +76,22 @@
}
CGFloat cellHeight = bounds.size.height / count;
NSColor *black = [NSColor blackColor];
NSColor *darkGray = [NSColor colorWithDeviceWhite:0.7 alpha:1.0];
NSColor *lightGray = [NSColor colorWithDeviceWhite:0.8 alpha:1.0];
NSColor *clrCandidateBG = colorFromRGBA(28,28,28,255);
NSColor *clrCandidateTextIndex = colorFromRGBA(233,233,233,213);
NSColor *clrCandidateSelectedBG = [NSColor alternateSelectedControlColor];
NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
[style setAlignment:NSCenterTextAlignment];
NSDictionary *textAttr = [NSDictionary dictionaryWithObjectsAndKeys:
_keyLabelFont, NSFontAttributeName,
black, NSForegroundColorAttributeName,
clrCandidateTextIndex, NSForegroundColorAttributeName,
style, NSParagraphStyleAttributeName,
nil];
for (NSUInteger index = 0; index < count; index++) {
NSRect textRect = NSMakeRect(0.0, index * cellHeight + _labelOffsetY, bounds.size.width, cellHeight - _labelOffsetY);
NSRect cellRect = NSMakeRect(0.0, index * cellHeight, bounds.size.width, cellHeight - 1);
NSRect cellRect = NSMakeRect(0.0, index * cellHeight, bounds.size.width, cellHeight);
// fill in the last cell
if (index + 1 >= count) {
@ -89,10 +99,10 @@
}
if (index == _highlightedIndex) {
[darkGray setFill];
[clrCandidateSelectedBG setFill];
}
else {
[lightGray setFill];
[clrCandidateBG setFill];
}
[NSBezierPath fillRect:cellRect];