From 317dcc384870307cb0c2d099d1742fe6201e9310 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Mon, 10 Jan 2022 18:27:05 +0800 Subject: [PATCH] =?UTF-8?q?=E5=80=99=E9=81=B8=E7=AA=97=E6=A0=BC=EF=BC=9A?= =?UTF-8?q?=E7=BE=8E=E5=8C=96=20Voltaire=20=E9=81=B8=E5=AD=97=E7=AA=97?= =?UTF-8?q?=E7=9A=84=E7=BE=8E=E8=A1=93=E9=A2=A8=E6=A0=BC=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 之前的設計的審美是 macOS 10.5 Leopard 時代的,從 macOS 10.7 開始掉渣。由於威注音的最低系統需求早已至 macOS 10.12 Sierra,故盡量利用現代 macOS 系統的 Cocoa 桌面美術特性。 --- .../VTHorizontalCandidateController.m | 28 +++++--- .../CandidateUI/VTHorizontalCandidateView.m | 47 +++++++----- .../VTVerticalCandidateController.m | 71 ++++++++++++++----- .../CandidateUI/VTVerticalKeyLabelStripView.m | 30 +++++--- 4 files changed, 121 insertions(+), 55 deletions(-) diff --git a/Source/CandidateUI/VTHorizontalCandidateController.m b/Source/CandidateUI/VTHorizontalCandidateController.m index 2c5e47c6..61cf9a1d 100644 --- a/Source/CandidateUI/VTHorizontalCandidateController.m +++ b/Source/CandidateUI/VTHorizontalCandidateController.m @@ -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]; diff --git a/Source/CandidateUI/VTHorizontalCandidateView.m b/Source/CandidateUI/VTHorizontalCandidateView.m index 528928d0..a26752d1 100644 --- a/Source/CandidateUI/VTHorizontalCandidateView.m +++ b/Source/CandidateUI/VTHorizontalCandidateView.m @@ -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; diff --git a/Source/CandidateUI/VTVerticalCandidateController.m b/Source/CandidateUI/VTVerticalCandidateController.m index 68c340b5..ba4c3239 100644 --- a/Source/CandidateUI/VTVerticalCandidateController.m +++ b/Source/CandidateUI/VTVerticalCandidateController.m @@ -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 diff --git a/Source/CandidateUI/VTVerticalKeyLabelStripView.m b/Source/CandidateUI/VTVerticalKeyLabelStripView.m index 1770d9f8..7469dc54 100644 --- a/Source/CandidateUI/VTVerticalKeyLabelStripView.m +++ b/Source/CandidateUI/VTVerticalKeyLabelStripView.m @@ -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];