diff --git a/McBopomofo.xcodeproj/project.pbxproj b/McBopomofo.xcodeproj/project.pbxproj index de626830..f1d8da46 100644 --- a/McBopomofo.xcodeproj/project.pbxproj +++ b/McBopomofo.xcodeproj/project.pbxproj @@ -12,12 +12,6 @@ 6A0D4ED015FC0D6400ABF4B3 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6A0D4EC415FC0D6400ABF4B3 /* AppDelegate.m */; }; 6A0D4ED215FC0D6400ABF4B3 /* InputMethodController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6A0D4EC715FC0D6400ABF4B3 /* InputMethodController.mm */; }; 6A0D4ED315FC0D6400ABF4B3 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6A0D4EC815FC0D6400ABF4B3 /* main.m */; }; - 6A0D4EFE15FC0DA600ABF4B3 /* VTCandidateController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6A0D4EDA15FC0DA600ABF4B3 /* VTCandidateController.m */; }; - 6A0D4EFF15FC0DA600ABF4B3 /* VTHorizontalCandidateController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6A0D4EDC15FC0DA600ABF4B3 /* VTHorizontalCandidateController.m */; }; - 6A0D4F0015FC0DA600ABF4B3 /* VTHorizontalCandidateView.m in Sources */ = {isa = PBXBuildFile; fileRef = 6A0D4EDE15FC0DA600ABF4B3 /* VTHorizontalCandidateView.m */; }; - 6A0D4F0115FC0DA600ABF4B3 /* VTVerticalCandidateController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6A0D4EE015FC0DA600ABF4B3 /* VTVerticalCandidateController.m */; }; - 6A0D4F0215FC0DA600ABF4B3 /* VTVerticalCandidateTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 6A0D4EE215FC0DA600ABF4B3 /* VTVerticalCandidateTableView.m */; }; - 6A0D4F0315FC0DA600ABF4B3 /* VTVerticalKeyLabelStripView.m in Sources */ = {isa = PBXBuildFile; fileRef = 6A0D4EE415FC0DA600ABF4B3 /* VTVerticalKeyLabelStripView.m */; }; 6A0D4F0815FC0DA600ABF4B3 /* Bopomofo.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 6A0D4EEF15FC0DA600ABF4B3 /* Bopomofo.tiff */; }; 6A0D4F0915FC0DA600ABF4B3 /* Bopomofo@2x.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 6A0D4EF015FC0DA600ABF4B3 /* Bopomofo@2x.tiff */; }; 6A0D4F4515FC0EB100ABF4B3 /* Mandarin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6A0D4F2015FC0EB100ABF4B3 /* Mandarin.cpp */; }; @@ -84,18 +78,6 @@ 6A0D4EC615FC0D6400ABF4B3 /* InputMethodController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InputMethodController.h; sourceTree = ""; }; 6A0D4EC715FC0D6400ABF4B3 /* InputMethodController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = InputMethodController.mm; sourceTree = ""; }; 6A0D4EC815FC0D6400ABF4B3 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6A0D4ED915FC0DA600ABF4B3 /* VTCandidateController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VTCandidateController.h; sourceTree = ""; }; - 6A0D4EDA15FC0DA600ABF4B3 /* VTCandidateController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VTCandidateController.m; sourceTree = ""; }; - 6A0D4EDB15FC0DA600ABF4B3 /* VTHorizontalCandidateController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VTHorizontalCandidateController.h; sourceTree = ""; }; - 6A0D4EDC15FC0DA600ABF4B3 /* VTHorizontalCandidateController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VTHorizontalCandidateController.m; sourceTree = ""; }; - 6A0D4EDD15FC0DA600ABF4B3 /* VTHorizontalCandidateView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VTHorizontalCandidateView.h; sourceTree = ""; }; - 6A0D4EDE15FC0DA600ABF4B3 /* VTHorizontalCandidateView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VTHorizontalCandidateView.m; sourceTree = ""; }; - 6A0D4EDF15FC0DA600ABF4B3 /* VTVerticalCandidateController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VTVerticalCandidateController.h; sourceTree = ""; }; - 6A0D4EE015FC0DA600ABF4B3 /* VTVerticalCandidateController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VTVerticalCandidateController.m; sourceTree = ""; }; - 6A0D4EE115FC0DA600ABF4B3 /* VTVerticalCandidateTableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VTVerticalCandidateTableView.h; sourceTree = ""; }; - 6A0D4EE215FC0DA600ABF4B3 /* VTVerticalCandidateTableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VTVerticalCandidateTableView.m; sourceTree = ""; }; - 6A0D4EE315FC0DA600ABF4B3 /* VTVerticalKeyLabelStripView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VTVerticalKeyLabelStripView.h; sourceTree = ""; }; - 6A0D4EE415FC0DA600ABF4B3 /* VTVerticalKeyLabelStripView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VTVerticalKeyLabelStripView.m; sourceTree = ""; }; 6A0D4EEF15FC0DA600ABF4B3 /* Bopomofo.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = Bopomofo.tiff; sourceTree = ""; }; 6A0D4EF015FC0DA600ABF4B3 /* Bopomofo@2x.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = "Bopomofo@2x.tiff"; sourceTree = ""; }; 6A0D4EF515FC0DA600ABF4B3 /* McBopomofo-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "McBopomofo-Info.plist"; sourceTree = ""; }; @@ -269,18 +251,6 @@ D47F7DD9278C32CD002F9DD7 /* CandidateController.swift */, D47F7DDB278C39EC002F9DD7 /* HorizontalCandidateController.swift */, D427F75E278C74B7004A2160 /* VerticalCandidateController.swift */, - 6A0D4ED915FC0DA600ABF4B3 /* VTCandidateController.h */, - 6A0D4EDA15FC0DA600ABF4B3 /* VTCandidateController.m */, - 6A0D4EDB15FC0DA600ABF4B3 /* VTHorizontalCandidateController.h */, - 6A0D4EDC15FC0DA600ABF4B3 /* VTHorizontalCandidateController.m */, - 6A0D4EDD15FC0DA600ABF4B3 /* VTHorizontalCandidateView.h */, - 6A0D4EDE15FC0DA600ABF4B3 /* VTHorizontalCandidateView.m */, - 6A0D4EDF15FC0DA600ABF4B3 /* VTVerticalCandidateController.h */, - 6A0D4EE015FC0DA600ABF4B3 /* VTVerticalCandidateController.m */, - 6A0D4EE115FC0DA600ABF4B3 /* VTVerticalCandidateTableView.h */, - 6A0D4EE215FC0DA600ABF4B3 /* VTVerticalCandidateTableView.m */, - 6A0D4EE315FC0DA600ABF4B3 /* VTVerticalKeyLabelStripView.h */, - 6A0D4EE415FC0DA600ABF4B3 /* VTVerticalKeyLabelStripView.m */, ); path = CandidateUI; sourceTree = ""; @@ -581,15 +551,9 @@ 6A0D4ED215FC0D6400ABF4B3 /* InputMethodController.mm in Sources */, 6A0D4ED315FC0D6400ABF4B3 /* main.m in Sources */, D47F7DD5278C25A0002F9DD7 /* InputSourceHelper.swift in Sources */, - 6A0D4EFE15FC0DA600ABF4B3 /* VTCandidateController.m in Sources */, - 6A0D4EFF15FC0DA600ABF4B3 /* VTHorizontalCandidateController.m in Sources */, D47F7DD3278C1263002F9DD7 /* UserOverrideModel.cpp in Sources */, D47F7DDC278C39EC002F9DD7 /* HorizontalCandidateController.swift in Sources */, - 6A0D4F0015FC0DA600ABF4B3 /* VTHorizontalCandidateView.m in Sources */, D427F75F278C74B7004A2160 /* VerticalCandidateController.swift in Sources */, - 6A0D4F0115FC0DA600ABF4B3 /* VTVerticalCandidateController.m in Sources */, - 6A0D4F0215FC0DA600ABF4B3 /* VTVerticalCandidateTableView.m in Sources */, - 6A0D4F0315FC0DA600ABF4B3 /* VTVerticalKeyLabelStripView.m in Sources */, D47F7DD0278C0897002F9DD7 /* NonModalAlertWindowController.swift in Sources */, D47F7DDA278C32CD002F9DD7 /* CandidateController.swift in Sources */, D427A9C125ED28CC005D43E0 /* OpenCCBridge.swift in Sources */, diff --git a/Source/CandidateUI/CandidateController.swift b/Source/CandidateUI/CandidateController.swift index f0595c7f..4d77d916 100644 --- a/Source/CandidateUI/CandidateController.swift +++ b/Source/CandidateUI/CandidateController.swift @@ -1,13 +1,13 @@ import Cocoa -@objc(CandidateControllerDelegate) +@objc(VTCandidateControllerDelegate) public protocol CandidateControllerDelegate: AnyObject { func candidateCountForController(_ controller: CandidateController) -> UInt func candidateController(_ controller: CandidateController, candidateAtIndex index: UInt) -> String func candidateController(_ controller: CandidateController, didSelectCandidateAtIndex index: UInt) } -@objc(CandidateController) +@objc(VTCandidateController) public class CandidateController: NSWindowController { @objc public weak var delegate: CandidateControllerDelegate? @objc public var selectedCandidateIndex: UInt = UInt.max @@ -42,22 +42,33 @@ public class CandidateController: NSWindowController { } @objc public func showNextPage() -> Bool { - return false + false } @objc public func showPreviousPage() -> Bool { - return false + false } @objc public func highlightNextCandidate() -> Bool { - return false + false } @objc public func highlightPreviousCandidate() -> Bool { - return false + false } - func set(windowTopLeftPoint: NSPoint, bottomOutOfScreenAdjustmentHeight height:CGFloat) { + @objc public func candidateIndexAtKeyLabelIndex(_ index: UInt) -> UInt { + UInt.max + } + + @objc(setWindowTopLeftPoint:bottomOutOfScreenAdjustmentHeight:) + func set(windowTopLeftPoint: NSPoint, bottomOutOfScreenAdjustmentHeight height: CGFloat) { + DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()) { + self.doSet(windowTopLeftPoint: windowTopLeftPoint, bottomOutOfScreenAdjustmentHeight: height) + } + } + + func doSet(windowTopLeftPoint: NSPoint, bottomOutOfScreenAdjustmentHeight height: CGFloat) { var adjustedPoint = windowTopLeftPoint var adjustedHeight = height @@ -80,7 +91,7 @@ public class CandidateController: NSWindowController { let windowSize = window?.frame.size ?? NSSize.zero // bottom beneath the screen? - if adjustedPoint.y - windowSize.height < screenFrame.maxY { + if adjustedPoint.y - windowSize.height < screenFrame.minY { adjustedPoint.y = windowTopLeftPoint.y + adjustedHeight + windowSize.height } @@ -91,7 +102,7 @@ public class CandidateController: NSWindowController { // right if adjustedPoint.x + windowSize.width >= screenFrame.maxX { - adjustedPoint.x = NSMaxX(screenFrame) - windowSize.width + adjustedPoint.x = screenFrame.maxX - windowSize.width } // left diff --git a/Source/CandidateUI/HorizontalCandidateController.swift b/Source/CandidateUI/HorizontalCandidateController.swift index ff28cc8e..dd27e8f6 100644 --- a/Source/CandidateUI/HorizontalCandidateController.swift +++ b/Source/CandidateUI/HorizontalCandidateController.swift @@ -159,7 +159,7 @@ fileprivate class HorizontalCandidateView: NSView { } } -@objc(HorizontalCandidateController) +@objc(VTHorizontalCandidateController) public class HorizontalCandidateController : CandidateController { private var candidateView: HorizontalCandidateView private var prevPageButton: NSButton @@ -267,7 +267,7 @@ public class HorizontalCandidateController : CandidateController { return true } - @objc public func candidateIndexAtKeyLabelIndex(_ index: UInt) -> UInt { + public override func candidateIndexAtKeyLabelIndex(_ index: UInt) -> UInt { guard let delegate = delegate else { return UInt.max } diff --git a/Source/CandidateUI/VTCandidateController.h b/Source/CandidateUI/VTCandidateController.h deleted file mode 100644 index 41e36a5c..00000000 --- a/Source/CandidateUI/VTCandidateController.h +++ /dev/null @@ -1,68 +0,0 @@ -// -// VTCandidateController.h -// -// Copyright (c) 2012 Lukhnos D. Liu (http://lukhnos.org) -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#import - -@class VTCandidateController; - -@protocol VTCandidateControllerDelegate -- (NSUInteger)candidateCountForController:(VTCandidateController *)controller; -- (NSString *)candidateController:(VTCandidateController *)controller candidateAtIndex:(NSUInteger)index; -- (void)candidateController:(VTCandidateController *)controller didSelectCandidateAtIndex:(NSUInteger)index; -@end - -@interface VTCandidateController : NSWindowController -{ -@protected - __weak id _delegate; - NSArray *_keyLabels; - NSFont *_keyLabelFont; - NSFont *_candidateFont; - BOOL _visible; -} - -- (void)reloadData; - -- (BOOL)showNextPage; -- (BOOL)showPreviousPage; -- (BOOL)highlightNextCandidate; -- (BOOL)highlightPreviousCandidate; - -- (void)setWindowTopLeftPoint:(NSPoint)topLeftPoint bottomOutOfScreenAdjustmentHeight:(CGFloat)height; - -- (NSUInteger)candidateIndexAtKeyLabelIndex:(NSUInteger)index; - -@property (weak, nonatomic) id delegate; -@property (assign, nonatomic) NSUInteger selectedCandidateIndex; - -@property (assign, nonatomic) BOOL visible; -@property (assign, nonatomic) NSPoint windowTopLeftPoint; - -@property (copy, nonatomic) NSArray *keyLabels; -@property (copy, nonatomic) NSFont *keyLabelFont; -@property (copy, nonatomic) NSFont *candidateFont; -@end diff --git a/Source/CandidateUI/VTCandidateController.m b/Source/CandidateUI/VTCandidateController.m deleted file mode 100644 index 933d1018..00000000 --- a/Source/CandidateUI/VTCandidateController.m +++ /dev/null @@ -1,178 +0,0 @@ -// -// VTCandidateController.m -// -// Copyright (c) 2012 Lukhnos D. Liu (http://lukhnos.org) -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#import "VTCandidateController.h" - - -@implementation VTCandidateController -@synthesize delegate = _delegate; -@synthesize keyLabels = _keyLabels; -@synthesize keyLabelFont = _keyLabelFont; -@synthesize candidateFont = _candidateFont; - -- (void)dealloc -{ - _keyLabels = nil; - _keyLabelFont = nil; - _candidateFont = nil; -} - -- (id)initWithWindow:(NSWindow *)window -{ - self = [super initWithWindow:window]; - if (self) { - // populate the default values - _keyLabels = @[@"1", @"2", @"3", @"4", @"5", @"6", @"7", @"8", @"9"]; - _keyLabelFont = [NSFont systemFontOfSize:14.0]; - _candidateFont = [NSFont systemFontOfSize:18.0]; - } - return self; -} - -- (void)reloadData -{ -} - -- (BOOL)showNextPage -{ - return NO; -} - -- (BOOL)showPreviousPage -{ - return NO; -} - -- (BOOL)highlightNextCandidate -{ - return NO; -} - -- (BOOL)highlightPreviousCandidate -{ - return NO; -} - -- (void)setWindowTopLeftPoint:(NSPoint)topLeftPoint bottomOutOfScreenAdjustmentHeight:(CGFloat)height -{ - // Since layout is now deferred, the origin setting should also be deferred so that - // the correct visible frame dimensions are used. - NSArray *params = [NSArray arrayWithObjects:[NSValue valueWithPoint:topLeftPoint], [NSNumber numberWithDouble:height], nil]; - [self performSelector:@selector(deferredSetWindowTopLeftPoint:) withObject:params afterDelay:0.0]; -} - -- (void)deferredSetWindowTopLeftPoint:(NSArray *)params -{ - NSPoint topLeftPoint = [[params objectAtIndex:0] pointValue]; - CGFloat height = [[params objectAtIndex:1] doubleValue]; - - NSPoint adjustedPoint = topLeftPoint; - CGFloat adjustedHeight = height; - - // first, locate the screen the point is in - NSRect screenFrame = [[NSScreen mainScreen] visibleFrame]; - - for (NSScreen *screen in [NSScreen screens]) { - NSRect frame = [screen visibleFrame]; - if (topLeftPoint.x >= NSMinX(frame) && topLeftPoint.x <= NSMaxX(frame) && topLeftPoint.y >= NSMinY(frame) && topLeftPoint.y <= NSMaxY(frame)) { - screenFrame = frame; - break; - } - } - - // make sure we don't have any erratic value - if (adjustedHeight > screenFrame.size.height / 2.0) { - adjustedHeight = 0.0; - } - - NSSize windowSize = [[self window] frame].size; - - // bottom beneath the screen? - if (adjustedPoint.y - windowSize.height < NSMinY(screenFrame)) { - adjustedPoint.y = topLeftPoint.y + adjustedHeight + windowSize.height; - } - - // top over the screen? - if (adjustedPoint.y >= NSMaxY(screenFrame)) { - adjustedPoint.y = NSMaxY(screenFrame) - 1.0; - } - - // right - if (adjustedPoint.x + windowSize.width >= NSMaxX(screenFrame)) { - adjustedPoint.x = NSMaxX(screenFrame) - windowSize.width; - } - - // left - if (adjustedPoint.x < NSMinX(screenFrame)) { - adjustedPoint.x = NSMinX(screenFrame); - } - - [[self window] setFrameTopLeftPoint:adjustedPoint]; -} - -- (NSUInteger)candidateIndexAtKeyLabelIndex:(NSUInteger)index -{ - return NSUIntegerMax; -} - -- (BOOL)visible -{ - // Because setVisible: defers its action, we need to use our own visible. Do not use [[self window] isVisible]. - return _visible; -} - -- (void)setVisible:(BOOL)visible -{ - _visible = visible; - if (visible) { - [[self window] performSelector:@selector(orderFront:) withObject:self afterDelay:0.0]; - } - else { - [[self window] performSelector:@selector(orderOut:) withObject:self afterDelay:0.0]; - } -} - -- (NSPoint)windowTopLeftPoint -{ - NSRect frameRect = [[self window] frame]; - return NSMakePoint(frameRect.origin.x, frameRect.origin.y + frameRect.size.height); -} - -- (void)setWindowTopLeftPoint:(NSPoint)topLeftPoint -{ - [self setWindowTopLeftPoint:topLeftPoint bottomOutOfScreenAdjustmentHeight:0.0]; -} - -- (NSUInteger)selectedCandidateIndex -{ - return NSUIntegerMax; -} - -- (void)setSelectedCandidateIndex:(NSUInteger)newIndex -{ -} -@end diff --git a/Source/CandidateUI/VTHorizontalCandidateController.h b/Source/CandidateUI/VTHorizontalCandidateController.h deleted file mode 100644 index 23c9da4e..00000000 --- a/Source/CandidateUI/VTHorizontalCandidateController.h +++ /dev/null @@ -1,40 +0,0 @@ -// -// VTHorizontalCandidateController.h -// -// Copyright (c) 2012 Lukhnos D. Liu (http://lukhnos.org) -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#import "VTCandidateController.h" - -@class VTHorizontalCandidateView; - -@interface VTHorizontalCandidateController : VTCandidateController -{ -@protected - VTHorizontalCandidateView *_candidateView; - NSButton *_prevPageButton; - NSButton *_nextPageButton; - NSUInteger _currentPage; -} -@end diff --git a/Source/CandidateUI/VTHorizontalCandidateController.m b/Source/CandidateUI/VTHorizontalCandidateController.m deleted file mode 100644 index 4cc8795b..00000000 --- a/Source/CandidateUI/VTHorizontalCandidateController.m +++ /dev/null @@ -1,250 +0,0 @@ -// -// VTHorizontalCandidateController.m -// -// Copyright (c) 2012 Lukhnos D. Liu (http://lukhnos.org) -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#import "VTHorizontalCandidateController.h" -#import "VTHorizontalCandidateView.h" - -@interface VTHorizontalCandidateController (Private) -- (NSUInteger)pageCount; -- (void)layoutCandidateView; -- (void)pageButtonAction:(id)sender; -- (void)candidateViewMouseDidClick:(id)sender; -@end - - -@implementation VTHorizontalCandidateController - -- (void)dealloc -{ - _candidateView = nil; - _prevPageButton = nil; - _nextPageButton = nil; -} - -- (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]; - - self = [self initWithWindow:panel]; - if (self) { - contentRect.origin = NSMakePoint(0.0, 0.0); - _candidateView = [[VTHorizontalCandidateView alloc] initWithFrame:contentRect]; - _candidateView.target = self; - _candidateView.action = @selector(candidateViewMouseDidClick:); - [[panel contentView] addSubview:_candidateView]; - - contentRect.size = NSMakeSize(36.0, 20.0); - _nextPageButton = [[NSButton alloc] initWithFrame:contentRect]; - _prevPageButton = [[NSButton alloc] initWithFrame:contentRect]; - [_nextPageButton setButtonType:NSMomentaryLightButton]; - [_nextPageButton setBezelStyle:NSSmallSquareBezelStyle]; - [_nextPageButton setTitle:@"»"]; - [_nextPageButton setTarget:self]; - [_nextPageButton setAction:@selector(pageButtonAction:)]; - - [_prevPageButton setButtonType:NSMomentaryLightButton]; - [_prevPageButton setBezelStyle:NSSmallSquareBezelStyle]; - [_prevPageButton setTitle:@"«"]; - [_prevPageButton setTarget:self]; - [_prevPageButton setAction:@selector(pageButtonAction:)]; - - [[panel contentView] addSubview:_nextPageButton]; - [[panel contentView] addSubview:_prevPageButton]; - } - - return self; -} - -- (void)reloadData -{ - _candidateView.highlightedIndex = 0; - _currentPage = 0; - [self layoutCandidateView]; -} - -- (BOOL)showNextPage -{ - if (_currentPage + 1 >= [self pageCount]) { - return NO; - } - - _currentPage++; - _candidateView.highlightedIndex = 0; - [self layoutCandidateView]; - return YES; -} - -- (BOOL)showPreviousPage -{ - if (_currentPage == 0) { - return NO; - } - - _currentPage--; - _candidateView.highlightedIndex = 0; - [self layoutCandidateView]; - return YES; -} - -- (BOOL)highlightNextCandidate -{ - NSUInteger currentIndex = self.selectedCandidateIndex; - if (currentIndex + 1 >= [_delegate candidateCountForController:self]) { - return NO; - } - - self.selectedCandidateIndex = currentIndex + 1; - return YES; -} - -- (BOOL)highlightPreviousCandidate -{ - NSUInteger currentIndex = self.selectedCandidateIndex; - if (currentIndex == 0) { - return NO; - } - - self.selectedCandidateIndex = currentIndex - 1; - return YES; -} - -- (NSUInteger)candidateIndexAtKeyLabelIndex:(NSUInteger)index -{ - NSUInteger result = _currentPage * [_keyLabels count] + index; - return result < [_delegate candidateCountForController:self] ? result : NSUIntegerMax; -} - - -- (NSUInteger)selectedCandidateIndex -{ - return _currentPage * [_keyLabels count] + _candidateView.highlightedIndex; -} - -- (void)setSelectedCandidateIndex:(NSUInteger)newIndex -{ - NSUInteger keyLabelCount = [_keyLabels count]; - if (newIndex < [_delegate candidateCountForController:self]) { - _currentPage = newIndex / keyLabelCount; - _candidateView.highlightedIndex = newIndex % keyLabelCount; - [self layoutCandidateView]; - } -} -@end - - -@implementation VTHorizontalCandidateController (Private) -- (NSUInteger)pageCount -{ - NSUInteger totalCount = [_delegate candidateCountForController:self]; - NSUInteger keyLabelCount = [_keyLabels count]; - return totalCount / keyLabelCount + ((totalCount % keyLabelCount) != 0 ? 1 : 0); -} - -- (void)layoutCandidateView -{ - [_candidateView setKeyLabelFont:_keyLabelFont candidateFont:_candidateFont]; - - NSMutableArray *candidates = [NSMutableArray array]; - NSUInteger count = [_delegate candidateCountForController:self]; - NSUInteger keyLabelCount = [_keyLabels count]; - for (NSUInteger index = _currentPage * keyLabelCount, j = 0; index < count && j < keyLabelCount; index++, j++) { - [candidates addObject:[_delegate candidateController:self candidateAtIndex:index]]; - } - - [_candidateView setKeyLabels:_keyLabels displayedCandidates:candidates]; - NSSize newSize = _candidateView.sizeForView; - - NSRect frameRect = [_candidateView frame]; - frameRect.size = newSize; - [_candidateView setFrame:frameRect]; - - if ([self pageCount] > 1) { - NSRect buttonRect = [_nextPageButton frame]; - CGFloat spacing = 0.0; - - if (newSize.height < 40.0) { - buttonRect.size.height = floor(newSize.height / 2); - } - else { - buttonRect.size.height = 20.0; - } - - if (newSize.height >= 60.0) { - spacing = ceil(newSize.height * 0.1); - } - - CGFloat buttonOriginY = (newSize.height - (buttonRect.size.height * 2.0 + spacing)) / 2.0; - buttonRect.origin = NSMakePoint(newSize.width + 8.0, buttonOriginY); - [_nextPageButton setFrame:buttonRect]; - - buttonRect.origin = NSMakePoint(newSize.width + 8.0, buttonOriginY + buttonRect.size.height + spacing); - [_prevPageButton setFrame:buttonRect]; - - [_nextPageButton setEnabled:(_currentPage + 1 < [self pageCount])]; - [_prevPageButton setEnabled:(_currentPage != 0)]; - - newSize.width += 52.0; - - [_nextPageButton setHidden:NO]; - [_prevPageButton setHidden:NO]; - } - else { - [_nextPageButton setHidden:YES]; - [_prevPageButton setHidden:YES]; - } - - frameRect = [[self window] frame]; - NSPoint topLeftPoint = NSMakePoint(frameRect.origin.x, frameRect.origin.y + frameRect.size.height); - - frameRect.size = newSize; - frameRect.origin = NSMakePoint(topLeftPoint.x, topLeftPoint.y - frameRect.size.height); - - [[self window] setFrame:frameRect display:NO]; - [_candidateView setNeedsDisplay:YES]; - -} - -- (void)pageButtonAction:(id)sender -{ - if (sender == _nextPageButton) { - [self showNextPage]; - } - else if (sender == _prevPageButton) { - [self showPreviousPage]; - } -} - -- (void)candidateViewMouseDidClick:(id)sender -{ - [_delegate candidateController:self didSelectCandidateAtIndex:self.selectedCandidateIndex]; -} -@end diff --git a/Source/CandidateUI/VTHorizontalCandidateView.h b/Source/CandidateUI/VTHorizontalCandidateView.h deleted file mode 100644 index 492b7c5c..00000000 --- a/Source/CandidateUI/VTHorizontalCandidateView.h +++ /dev/null @@ -1,54 +0,0 @@ -// -// VTHorizontalCandidateView.h -// -// Copyright (c) 2012 Lukhnos D. Liu (http://lukhnos.org) -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#import - -@interface VTHorizontalCandidateView : NSView -{ -@protected - NSArray *_keyLabels; - NSArray *_displayedCandidates; - CGFloat _keyLabelHeight; - CGFloat _candidateTextHeight; - CGFloat _cellPadding; - NSDictionary *_keyLabelAttrDict; - NSDictionary *_candidateAttrDict; - NSArray *_elementWidths; - NSUInteger _highlightedIndex; - NSUInteger _trackingHighlightedIndex; - SEL _action; - __weak id _target; -} - -- (void)setKeyLabels:(NSArray *)labels displayedCandidates:(NSArray *)candidates; -- (void)setKeyLabelFont:(NSFont *)labelFont candidateFont:(NSFont *)candidateFont; - -@property (readonly, nonatomic) NSSize sizeForView; -@property (assign, nonatomic) NSUInteger highlightedIndex; -@property (assign, nonatomic) SEL action; -@property (weak, nonatomic) id target; -@end diff --git a/Source/CandidateUI/VTHorizontalCandidateView.m b/Source/CandidateUI/VTHorizontalCandidateView.m deleted file mode 100644 index d24122f5..00000000 --- a/Source/CandidateUI/VTHorizontalCandidateView.m +++ /dev/null @@ -1,225 +0,0 @@ -// -// VTHorizontalCandidateView.m -// -// Copyright (c) 2012 Lukhnos D. Liu (http://lukhnos.org) -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#import "VTHorizontalCandidateView.h" - -// use these instead of MIN/MAX macro to keep compilers happy with pedantic warnings on -NS_INLINE CGFloat min(CGFloat a, CGFloat b) { return a < b ? a : b; } -NS_INLINE CGFloat max(CGFloat a, CGFloat b) { return a > b ? a : b; } - -@implementation VTHorizontalCandidateView - -@synthesize highlightedIndex = _highlightedIndex; -@synthesize action = _action; -@synthesize target = _target; - -- (void)dealloc -{ - _keyLabels = nil; - _displayedCandidates = nil; - _keyLabelAttrDict = nil; - _candidateAttrDict = nil; - _elementWidths = nil; -} - -- (void)setKeyLabels:(NSArray *)labels displayedCandidates:(NSArray *)candidates -{ - NSUInteger count = min([labels count], [candidates count]); - _keyLabels = [labels subarrayWithRange:NSMakeRange(0, count)]; - _displayedCandidates = [candidates subarrayWithRange:NSMakeRange(0, count)]; - - NSMutableArray *newWidths = [NSMutableArray array]; - - NSSize baseSize = NSMakeSize(10240.0, 10240.0); - for (NSUInteger index = 0; index < count; index++) { - NSRect labelRect = [[_keyLabels objectAtIndex:index] boundingRectWithSize:baseSize options:NSStringDrawingUsesLineFragmentOrigin attributes:_keyLabelAttrDict]; - - NSRect candidateRect = [[_displayedCandidates objectAtIndex:index] boundingRectWithSize:baseSize options:NSStringDrawingUsesLineFragmentOrigin attributes:_candidateAttrDict]; - - CGFloat width = max(labelRect.size.width, candidateRect.size.width) + _cellPadding; - [newWidths addObject:[NSNumber numberWithDouble:width]]; - } - - _elementWidths = newWidths; -} - -- (void)setKeyLabelFont:(NSFont *)labelFont candidateFont:(NSFont *)candidateFont -{ - NSMutableParagraphStyle *paraStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; - [paraStyle setAlignment:NSCenterTextAlignment]; - - _keyLabelAttrDict = [NSDictionary dictionaryWithObjectsAndKeys: - labelFont, NSFontAttributeName, - paraStyle, NSParagraphStyleAttributeName, - [NSColor blackColor], NSForegroundColorAttributeName, - nil]; - _candidateAttrDict = [NSDictionary dictionaryWithObjectsAndKeys: - candidateFont, NSFontAttributeName, - paraStyle, NSParagraphStyleAttributeName, - [NSColor textColor], NSForegroundColorAttributeName, - nil]; - - CGFloat labelFontSize = [labelFont pointSize]; - CGFloat candidateFontSize = [candidateFont pointSize]; - CGFloat biggestSize = max(labelFontSize, candidateFontSize); - - _keyLabelHeight = ceil(labelFontSize * 1.20); - _candidateTextHeight = ceil(candidateFontSize * 1.20); - _cellPadding = ceil(biggestSize / 2.0); -} - - -- (NSSize)sizeForView -{ - NSSize result = NSMakeSize(0.0, 0.0); - if ([_elementWidths count]) { - for (NSNumber *w in _elementWidths) { - result.width += [w doubleValue]; - } - - result.width += [_elementWidths count]; - result.height = _keyLabelHeight + _candidateTextHeight + 1.0; - } - - return result; -} - -- (BOOL)isFlipped -{ - return YES; -} - -- (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]; - - NSRect bounds = [self bounds]; - - [backgroundColor 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; - - 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); - - if (index == _highlightedIndex) { - [darkGray setFill]; - } - else { - [lightGray setFill]; - } - - [NSBezierPath fillRect:labelRect]; - [[_keyLabels objectAtIndex:index] drawInRect:labelRect withAttributes:_keyLabelAttrDict]; - - if (index == _highlightedIndex) { - [[NSColor selectedTextBackgroundColor] setFill]; - - activeCandidateAttr = [_candidateAttrDict mutableCopy]; - [(NSMutableDictionary *)activeCandidateAttr setObject:[NSColor selectedTextColor] forKey:NSForegroundColorAttributeName]; - } - else { - [backgroundColor setFill]; - } - - [NSBezierPath fillRect:candidateRect]; - [[_displayedCandidates objectAtIndex:index] drawInRect:candidateRect withAttributes:activeCandidateAttr]; - - accuWidth += currentWidth + 1.0; - } -} - -- (NSUInteger)findHitIndex:(NSEvent *)theEvent -{ - NSUInteger result = NSUIntegerMax; - - NSPoint location = [self convertPoint:[theEvent locationInWindow] toView:nil]; - if (!NSPointInRect(location, [self bounds])) { - return result; - } - - NSUInteger count = [_elementWidths count]; - CGFloat accuWidth = 0.0; - for (NSUInteger index = 0; index < count; index++) { - CGFloat currentWidth = [[_elementWidths objectAtIndex:index] doubleValue]; - - if (location.x >= accuWidth && location.x <= accuWidth + currentWidth) { - result = index; - break; - } - - accuWidth += currentWidth + 1.0; - } - - return result; -} - -- (void)mouseDown:(NSEvent *)theEvent -{ - NSUInteger newIndex = [self findHitIndex:theEvent]; - _trackingHighlightedIndex = _highlightedIndex; - - if (newIndex != NSUIntegerMax) { - _highlightedIndex = newIndex; - [self setNeedsDisplay:YES]; - } -} - -- (void)mouseUp:(NSEvent *)theEvent -{ - NSUInteger newIndex = [self findHitIndex:theEvent]; - BOOL triggerAction = NO; - - if (newIndex == _highlightedIndex) { - triggerAction = YES; - } - else { - _highlightedIndex = _trackingHighlightedIndex; - } - - _trackingHighlightedIndex = 0; - [self setNeedsDisplay:YES]; - -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Warc-performSelector-leaks" - if (triggerAction && _target && _action) { - [_target performSelector:_action withObject:self]; - } -# pragma clang diagnostic pop -} - -@end diff --git a/Source/CandidateUI/VTVerticalCandidateController.h b/Source/CandidateUI/VTVerticalCandidateController.h deleted file mode 100644 index 04bdb596..00000000 --- a/Source/CandidateUI/VTVerticalCandidateController.h +++ /dev/null @@ -1,41 +0,0 @@ -// -// VTVerticalCandidateController.h -// -// Copyright (c) 2012 Lukhnos D. Liu (http://lukhnos.org) -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#import "VTCandidateController.h" - -@class VTVerticalKeyLabelStripView; - -@interface VTVerticalCandidateController : VTCandidateController -{ -@protected - VTVerticalKeyLabelStripView *_keyLabelStripView; - NSScrollView *_scrollView; - NSTableView *_tableView; - NSMutableParagraphStyle *_candidateTextParagraphStyle; - CGFloat _maxCandidateAttrStringWidth; -} -@end diff --git a/Source/CandidateUI/VTVerticalCandidateController.m b/Source/CandidateUI/VTVerticalCandidateController.m deleted file mode 100644 index 7150d45b..00000000 --- a/Source/CandidateUI/VTVerticalCandidateController.m +++ /dev/null @@ -1,434 +0,0 @@ -// -// VTVerticalCandidateController.m -// -// Copyright (c) 2012 Lukhnos D. Liu (http://lukhnos.org) -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#import "VTVerticalCandidateController.h" -#import "VTVerticalKeyLabelStripView.h" -#import "VTVerticalCandidateTableView.h" - -// use these instead of MIN/MAX macro to keep compilers happy with pedantic warnings on -NS_INLINE CGFloat min(CGFloat a, CGFloat b) { return a < b ? a : b; } -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 const CGFloat kCandidateTextPaddingWithMandatedTableViewPadding = 18.0; -static const CGFloat kCandidateTextLeftMarginWithMandatedTableViewPadding = 0.0; -#endif - -@interface VTVerticalCandidateController (Private) -- (void)rowDoubleClicked:(id)sender; -- (BOOL)scrollPageByOne:(BOOL)forward; -- (BOOL)moveSelectionByOne:(BOOL)forward; -- (void)layoutCandidateView; -@end - -@implementation VTVerticalCandidateController -{ - // Total padding added to the left and the right of the table view cell text. - CGFloat _candidateTextPadding; - - // The indent of the table view cell text from the left. - CGFloat _candidateTextLeftMargin; -} - - -- (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]; - - 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]; - - [[panel contentView] addSubview:_keyLabelStripView]; - - NSRect scrollViewRect = contentRect; - scrollViewRect.origin.x = stripRect.size.width; - scrollViewRect.size.width -= stripRect.size.width; - - _scrollView = [[NSScrollView alloc] initWithFrame:scrollViewRect]; - - // >=10.7 only, elastic scroll causes some drawing issues with visible scroller, so we disable it - if ([_scrollView respondsToSelector:@selector(setVerticalScrollElasticity:)]) { - [_scrollView setVerticalScrollElasticity:NSScrollElasticityNone]; - } - - _tableView = [[VTVerticalCandidateTableView alloc] initWithFrame:contentRect]; - [_tableView setDataSource:self]; - [_tableView setDelegate:self]; - - NSTableColumn *column = [[NSTableColumn alloc] initWithIdentifier:@"candidate"]; - [column setDataCell:[[NSTextFieldCell alloc] init]]; - [column setEditable:NO]; - - _candidateTextPadding = kCandidateTextPadding; - _candidateTextLeftMargin = kCandidateTextLeftMargin; - - [_tableView addTableColumn:column]; - [_tableView setIntercellSpacing:NSMakeSize(0.0, 1.0)]; - [_tableView setHeaderView:nil]; - [_tableView setAllowsMultipleSelection:NO]; - [_tableView setAllowsEmptySelection:YES]; - [_tableView setDoubleAction:@selector(rowDoubleClicked:)]; - [_tableView setTarget:self]; - - #if defined(__MAC_10_16) - if (@available(macOS 10.16, *)) { - [_tableView setStyle:NSTableViewStyleFullWidth]; - _candidateTextPadding = kCandidateTextPaddingWithMandatedTableViewPadding; - _candidateTextLeftMargin = kCandidateTextLeftMarginWithMandatedTableViewPadding; - } - #endif - - [_scrollView setDocumentView:_tableView]; - [[panel contentView] addSubview:_scrollView]; - - _candidateTextParagraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; - [_candidateTextParagraphStyle setFirstLineHeadIndent:_candidateTextLeftMargin]; - [_candidateTextParagraphStyle setLineBreakMode:NSLineBreakByClipping]; - } - - return self; -} - -- (void)reloadData -{ - _maxCandidateAttrStringWidth = ceil([_candidateFont pointSize] * 2.0 + _candidateTextPadding); - - [_tableView reloadData]; - [self layoutCandidateView]; - - if ([_delegate candidateCountForController:self]) { - self.selectedCandidateIndex = 0; - } -} - -- (BOOL)showNextPage -{ - return [self scrollPageByOne:YES]; -} - -- (BOOL)showPreviousPage -{ - return [self scrollPageByOne:NO]; -} - -- (BOOL)highlightNextCandidate -{ - return [self moveSelectionByOne:YES]; -} - -- (BOOL)highlightPreviousCandidate -{ - return [self moveSelectionByOne:NO]; -} - -- (NSUInteger)candidateIndexAtKeyLabelIndex:(NSUInteger)index -{ - NSInteger firstVisibleRow = [_tableView rowAtPoint:[_scrollView documentVisibleRect].origin]; - if (firstVisibleRow != -1) { - NSUInteger result = firstVisibleRow + index; - if (result < [_delegate candidateCountForController:self]) { - return result; - } - } - - return NSUIntegerMax; -} - -- (NSUInteger)selectedCandidateIndex -{ - NSInteger selectedRow = [_tableView selectedRow]; - return (selectedRow == -1) ? NSUIntegerMax : selectedRow; -} - -- (void)setSelectedCandidateIndex:(NSUInteger)aNewIndex -{ - NSUInteger newIndex = aNewIndex; - - NSInteger selectedRow = [_tableView selectedRow]; - - NSUInteger labelCount = [_keyLabels count]; - NSUInteger itemCount = [_delegate candidateCountForController:self]; - - if (newIndex == NSUIntegerMax) { - if (itemCount == 0) { - [_tableView deselectAll:self]; - return; - } - newIndex = 0; - } - - NSUInteger lastVisibleRow = newIndex; - if (selectedRow != -1 && itemCount > 0 && itemCount > labelCount) { - if (newIndex > selectedRow && (newIndex - selectedRow) > 1) { - lastVisibleRow = min(newIndex + labelCount - 1, itemCount - 1); - } - - // no need to handle the backward case: (newIndex < selectedRow && selectedRow - newIndex > 1) - } - - if (itemCount > labelCount) { - [_tableView scrollRowToVisible:lastVisibleRow]; - } - - [_tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:newIndex] byExtendingSelection:NO]; -} - - -@end - - -@implementation VTVerticalCandidateController (Private) -- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView -{ - return [_delegate candidateCountForController:self]; -} - -- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row -{ - NSString *candidate = @""; - - // rendering can occur when the delegate is already gone or data goes stale; in that case we ignore it - - if (row < [_delegate candidateCountForController:self]) { - candidate = [_delegate candidateController:self candidateAtIndex:row]; - } - - NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:candidate attributes:[NSDictionary dictionaryWithObjectsAndKeys:_candidateFont, NSFontAttributeName, _candidateTextParagraphStyle, NSParagraphStyleAttributeName, nil]]; - - // we do more work than what this method is expected to; normally not a good practice, but for the amount of data (9 to 10 rows max), we can afford the overhead - - // expand the window width if text overflows - NSRect boundingRect = [attrString boundingRectWithSize:NSMakeSize(10240.0, 10240.0) options:NSStringDrawingUsesLineFragmentOrigin]; - CGFloat textWidth = boundingRect.size.width + _candidateTextPadding; - if (textWidth > _maxCandidateAttrStringWidth) { - _maxCandidateAttrStringWidth = textWidth; - [self layoutCandidateView]; - } - - // keep track of the highlighted index in the key label strip - NSUInteger count = [_keyLabels count]; - NSInteger selectedRow = [_tableView selectedRow]; - if (selectedRow != -1) { - // cast this into signed integer to make our life easier - NSInteger newHilightIndex; - - if (_keyLabelStripView.highlightedIndex != -1 && (row >= selectedRow + count || (selectedRow > count && row <= selectedRow - count))) { - newHilightIndex = -1; - } - else { - NSInteger firstVisibleRow = [_tableView rowAtPoint:[_scrollView documentVisibleRect].origin]; - - newHilightIndex = selectedRow - firstVisibleRow; - if (newHilightIndex < -1) { - newHilightIndex = -1; - } - } - - if (newHilightIndex != _keyLabelStripView.highlightedIndex && newHilightIndex >= 0) { - _keyLabelStripView.highlightedIndex = newHilightIndex; - [_keyLabelStripView setNeedsDisplay:YES]; - } - } - - return attrString; -} - -- (void)tableViewSelectionDidChange:(NSNotification *)aNotification -{ - NSInteger selectedRow = [_tableView selectedRow]; - if (selectedRow != -1) { - // keep track of the highlighted index in the key label strip - NSInteger firstVisibleRow = [_tableView rowAtPoint:[_scrollView documentVisibleRect].origin]; - _keyLabelStripView.highlightedIndex = selectedRow - firstVisibleRow; - [_keyLabelStripView setNeedsDisplay:YES]; - - // fix a subtle OS X "bug" that, since we force the scroller to appear, - // scrolling sometimes shows a temporarily "broken" scroll bar - // (but quickly disappears) - if ([_scrollView hasVerticalScroller]) { - [[_scrollView verticalScroller] setNeedsDisplay]; - } - } -} - -- (void)rowDoubleClicked:(id)sender -{ - NSInteger clickedRow = [_tableView clickedRow]; - if (clickedRow != -1) { - [_delegate candidateController:self didSelectCandidateAtIndex:clickedRow]; - } -} - -- (BOOL)scrollPageByOne:(BOOL)forward -{ - NSUInteger labelCount = [_keyLabels count]; - NSUInteger itemCount = [_delegate candidateCountForController:self]; - - if (0 == itemCount) { - return NO; - } - - if (itemCount <= labelCount) { - return NO; - } - - NSUInteger newIndex = self.selectedCandidateIndex; - - if (forward) { - if (newIndex == itemCount - 1) { - return NO; - } - - newIndex = min(newIndex + labelCount, itemCount - 1); - } - else { - if (newIndex == 0) { - return NO; - } - - if (newIndex < labelCount) { - newIndex = 0; - } - else { - newIndex -= labelCount; - } - } - - self.selectedCandidateIndex = newIndex; - return YES; -} - -- (BOOL)moveSelectionByOne:(BOOL)forward -{ - NSUInteger itemCount = [_delegate candidateCountForController:self]; - - if (0 == itemCount) { - return NO; - } - - NSUInteger newIndex = self.selectedCandidateIndex; - - if (forward) { - if (newIndex == itemCount - 1) { - return NO; - } - - newIndex++; - } - else { - if (0 == newIndex) { - return NO; - } - - newIndex--; - } - - self.selectedCandidateIndex = newIndex; - return YES; -} - -- (void)layoutCandidateView -{ - [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(doLayoutCanaditeView) object:nil]; - [self performSelector:@selector(doLayoutCanaditeView) withObject:nil afterDelay:0.0]; -} - -- (void)doLayoutCanaditeView -{ - NSUInteger count = [_delegate candidateCountForController:self]; - if (!count) { - return; - } - - CGFloat candidateFontSize = ceil([_candidateFont pointSize]); - CGFloat keyLabelFontSize = ceil([_keyLabelFont pointSize]); - CGFloat fontSize = max(candidateFontSize, keyLabelFontSize); - - NSControlSize controlSize = (fontSize > 36.0) ? NSRegularControlSize : NSSmallControlSize; - - NSUInteger keyLabelCount = [_keyLabels count]; - CGFloat scrollerWidth = 0.0; - if (count <= keyLabelCount) { - keyLabelCount = count; - [_scrollView setHasVerticalScroller:NO]; - } - else { - [_scrollView setHasVerticalScroller:YES]; - - NSScroller *verticalScroller = [_scrollView verticalScroller]; - [verticalScroller setControlSize:controlSize]; - [verticalScroller setScrollerStyle:NSScrollerStyleLegacy]; - scrollerWidth = [NSScroller scrollerWidthForControlSize:controlSize scrollerStyle:NSScrollerStyleLegacy]; - } - - _keyLabelStripView.keyLabelFont = _keyLabelFont; - _keyLabelStripView.keyLabels = [_keyLabels subarrayWithRange:NSMakeRange(0, keyLabelCount)]; - _keyLabelStripView.labelOffsetY = (keyLabelFontSize >= candidateFontSize) ? 0.0 : floor((candidateFontSize - keyLabelFontSize) / 2.0); - - CGFloat rowHeight = ceil(fontSize * 1.25); - [_tableView setRowHeight:rowHeight]; - - CGFloat maxKeyLabelWidth = keyLabelFontSize; - NSDictionary *textAttr = [NSDictionary dictionaryWithObjectsAndKeys: - _keyLabelFont, NSFontAttributeName, - nil]; - NSSize boundingBox = NSMakeSize(1600.0, 1600.0); - for (NSString *label in _keyLabels) { - NSRect rect = [label boundingRectWithSize:boundingBox options:NSStringDrawingUsesLineFragmentOrigin attributes:textAttr]; - maxKeyLabelWidth = max(rect.size.width, maxKeyLabelWidth); - } - - CGFloat rowSpacing = [_tableView intercellSpacing].height; - CGFloat stripWidth = ceil(maxKeyLabelWidth * 1.20); - CGFloat tableViewStartWidth = ceil(_maxCandidateAttrStringWidth + scrollerWidth);; - CGFloat windowWidth = stripWidth + 1.0 + tableViewStartWidth; - CGFloat windowHeight = keyLabelCount * (rowHeight + rowSpacing); - - NSRect frameRect = [[self window] frame]; - NSPoint topLeftPoint = NSMakePoint(frameRect.origin.x, frameRect.origin.y + frameRect.size.height); - - frameRect.size = NSMakeSize(windowWidth, windowHeight); - 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)]; - [[self window] setFrame:frameRect display:NO]; -} -@end diff --git a/Source/CandidateUI/VTVerticalCandidateTableView.h b/Source/CandidateUI/VTVerticalCandidateTableView.h deleted file mode 100644 index 47bb37ac..00000000 --- a/Source/CandidateUI/VTVerticalCandidateTableView.h +++ /dev/null @@ -1,31 +0,0 @@ -// -// VTVerticalCandidateTableView.h -// -// Copyright (c) 2012 Lukhnos D. Liu (http://lukhnos.org) -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#import - -@interface VTVerticalCandidateTableView : NSTableView -@end diff --git a/Source/CandidateUI/VTVerticalCandidateTableView.m b/Source/CandidateUI/VTVerticalCandidateTableView.m deleted file mode 100644 index bf326ac5..00000000 --- a/Source/CandidateUI/VTVerticalCandidateTableView.m +++ /dev/null @@ -1,38 +0,0 @@ -// -// VTVerticalCandidateTableView.m -// -// Copyright (c) 2012 Lukhnos D. Liu (http://lukhnos.org) -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#import "VTVerticalCandidateTableView.h" - -@implementation VTVerticalCandidateTableView -- (NSRect)adjustScroll:(NSRect)newVisible -{ - NSRect scrollRect = newVisible; - CGFloat rowHeightPlusSpacing = [self rowHeight] + [self intercellSpacing].height; - scrollRect.origin.y = (NSInteger)(scrollRect.origin.y / rowHeightPlusSpacing) * rowHeightPlusSpacing; - return scrollRect; -} -@end diff --git a/Source/CandidateUI/VTVerticalKeyLabelStripView.h b/Source/CandidateUI/VTVerticalKeyLabelStripView.h deleted file mode 100644 index 8439ba1a..00000000 --- a/Source/CandidateUI/VTVerticalKeyLabelStripView.h +++ /dev/null @@ -1,43 +0,0 @@ -// -// VTVerticalKeyLabelStripView.m -// -// Copyright (c) 2012 Lukhnos D. Liu (http://lukhnos.org) -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#import - -@interface VTVerticalKeyLabelStripView : NSView -{ -@protected - NSFont *_keyLabelFont; - CGFloat _labelOffsetY; - NSArray *_keyLabels; - NSInteger _highlightedIndex; -} - -@property (retain, nonatomic) NSFont *keyLabelFont; -@property (assign, nonatomic) CGFloat labelOffsetY; -@property (retain, nonatomic) NSArray *keyLabels; -@property (assign, nonatomic) NSInteger highlightedIndex; -@end diff --git a/Source/CandidateUI/VTVerticalKeyLabelStripView.m b/Source/CandidateUI/VTVerticalKeyLabelStripView.m deleted file mode 100644 index 1a7d2a19..00000000 --- a/Source/CandidateUI/VTVerticalKeyLabelStripView.m +++ /dev/null @@ -1,104 +0,0 @@ -// -// VTVerticalKeyLabelStripView.h -// -// Copyright (c) 2012 Lukhnos D. Liu (http://lukhnos.org) -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#import "VTVerticalKeyLabelStripView.h" - -@implementation VTVerticalKeyLabelStripView -@synthesize keyLabelFont = _keyLabelFont; -@synthesize labelOffsetY = _labelOffsetY; -@synthesize keyLabels = _keyLabels; -@synthesize highlightedIndex = _highlightedIndex; - -- (void)dealloc -{ - _keyLabelFont = nil; - _keyLabels = nil; -} - -- (id)initWithFrame:(NSRect)frameRect -{ - self = [super initWithFrame:frameRect]; - if (self) { - _keyLabelFont = [NSFont systemFontOfSize:[NSFont smallSystemFontSize]]; - } - - return self; -} - -- (BOOL)isFlipped -{ - return YES; -} - -- (void)drawRect:(NSRect)dirtyRect -{ - NSRect bounds = [self bounds]; - [[NSColor whiteColor] setFill]; - [NSBezierPath fillRect:bounds]; - - NSUInteger count = [_keyLabels count]; - if (!count) { - return; - } - - 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]; - - NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; - [style setAlignment:NSCenterTextAlignment]; - - NSDictionary *textAttr = [NSDictionary dictionaryWithObjectsAndKeys: - _keyLabelFont, NSFontAttributeName, - black, 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); - - // fill in the last cell - if (index + 1 >= count) { - cellRect.size.height += 1.0; - } - - if (index == _highlightedIndex) { - [darkGray setFill]; - } - else { - [lightGray setFill]; - } - - [NSBezierPath fillRect:cellRect]; - - NSString *text = [_keyLabels objectAtIndex:index]; - [text drawInRect:textRect withAttributes:textAttr]; - } -} -@end diff --git a/Source/CandidateUI/VerticalCandidateController.swift b/Source/CandidateUI/VerticalCandidateController.swift index 5bd15f51..05597597 100644 --- a/Source/CandidateUI/VerticalCandidateController.swift +++ b/Source/CandidateUI/VerticalCandidateController.swift @@ -63,7 +63,7 @@ private let kCandidateTextPaddingWithMandatedTableViewPadding = 18.0 private let kCandidateTextLeftMarginWithMandatedTableViewPadding = 0.0 -@objc(VerticalCandidateController) +@objc(VTVerticalCandidateController) public class VerticalCandidateController: CandidateController { private var keyLabelStripView: VerticalKeyLabelStripView private var scrollView: NSScrollView @@ -94,7 +94,7 @@ public class VerticalCandidateController: CandidateController { tableView = NSTableView(frame: contentRect) let column = NSTableColumn(identifier: NSUserInterfaceItemIdentifier(rawValue: "candidate")) - column.dataCell = NSTextFieldCell.self + column.dataCell = NSTextFieldCell() column.isEditable = false candidateTextPadding = kCandidateTextPadding @@ -160,7 +160,7 @@ public class VerticalCandidateController: CandidateController { moveSelectionByOne(false) } - @objc public func candidateIndexAtKeyLabelIndex(_ index: UInt) -> UInt { + public override func candidateIndexAtKeyLabelIndex(_ index: UInt) -> UInt { guard let delegate = delegate else { return UInt.max } diff --git a/Source/InputMethodController.mm b/Source/InputMethodController.mm index c5ca590f..d5b8278a 100644 --- a/Source/InputMethodController.mm +++ b/Source/InputMethodController.mm @@ -39,8 +39,6 @@ #import "OVStringHelper.h" #import "OVUTF8Helper.h" #import "AppDelegate.h" -#import "VTHorizontalCandidateController.h" -#import "VTVerticalCandidateController.h" #import "McBopomofo-Swift.h" //@import SwiftUI; @@ -285,9 +283,6 @@ static double FindHighestScore(const vector& nodes, double epsilon) NSMenuItem *aboutMenuItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"About McBopomofo…", @"") action:@selector(showAbout:) keyEquivalent:@""]; [menu addItem:aboutMenuItem]; - - NSLog(@"menu %@", menu); - return menu; }