From 40e3b53b274a490a9012cd0f3df77982539c1cc3 Mon Sep 17 00:00:00 2001 From: LEOYoon-Tsaw Date: Thu, 30 Sep 2021 18:56:45 -0400 Subject: [PATCH] Full support for translucency --- Squirrel Designer.xcodeproj/project.pbxproj | 16 ++--- Squirrel Designer/Base.lproj/Main.storyboard | 27 ++++++-- Squirrel Designer/LayoutModel.swift | 67 ++++++++++++++++++-- Squirrel Designer/ViewController.swift | 6 ++ Squirrel Designer/zh-Hans.lproj/Main.strings | 3 + Squirrel Designer/zh-Hant.lproj/Main.strings | 3 + 6 files changed, 102 insertions(+), 20 deletions(-) diff --git a/Squirrel Designer.xcodeproj/project.pbxproj b/Squirrel Designer.xcodeproj/project.pbxproj index 4866ac4..cd62188 100644 --- a/Squirrel Designer.xcodeproj/project.pbxproj +++ b/Squirrel Designer.xcodeproj/project.pbxproj @@ -24,8 +24,8 @@ D24509952621F4AF00EB4BAC /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = ""; }; D2830BBA24FEC87E00BF44BE /* Template.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Template.swift; sourceTree = ""; }; D2830BBE24FEFDD400BF44BE /* CodeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodeView.swift; sourceTree = ""; }; - D2A25D2F262211D20008E455 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/Main.strings"; sourceTree = ""; }; - D2A25D31262212A90008E455 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Main.strings"; sourceTree = ""; }; + D2A48D2F2707BDA7002F5086 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Main.strings"; sourceTree = ""; }; + D2A48D312707BDBD002F5086 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/Main.strings"; sourceTree = ""; }; D2B5B51C24FD85CA00F7304E /* Squirrel Designer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Squirrel Designer.app"; sourceTree = BUILT_PRODUCTS_DIR; }; D2B5B51F24FD85CA00F7304E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; D2B5B52124FD85CA00F7304E /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; @@ -170,8 +170,8 @@ isa = PBXVariantGroup; children = ( D24509832621E8D800EB4BAC /* Base */, - D2A25D2F262211D20008E455 /* zh-Hant */, - D2A25D31262212A90008E455 /* zh-Hans */, + D2A48D2F2707BDA7002F5086 /* zh-Hans */, + D2A48D312707BDBD002F5086 /* zh-Hant */, ); name = Main.storyboard; sourceTree = ""; @@ -315,7 +315,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 18; + CURRENT_PROJECT_VERSION = 19; DEVELOPMENT_TEAM = 28HU5A7B46; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = "Squirrel Designer/Info.plist"; @@ -324,7 +324,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 1.6; + MARKETING_VERSION = 1.7; PRODUCT_BUNDLE_IDENTIFIER = "Rime.Squirrel-Designer"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; @@ -339,7 +339,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 18; + CURRENT_PROJECT_VERSION = 19; DEVELOPMENT_TEAM = 28HU5A7B46; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = "Squirrel Designer/Info.plist"; @@ -348,7 +348,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 1.6; + MARKETING_VERSION = 1.7; PRODUCT_BUNDLE_IDENTIFIER = "Rime.Squirrel-Designer"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; diff --git a/Squirrel Designer/Base.lproj/Main.storyboard b/Squirrel Designer/Base.lproj/Main.storyboard index 5570e53..584f8c2 100644 --- a/Squirrel Designer/Base.lproj/Main.storyboard +++ b/Squirrel Designer/Base.lproj/Main.storyboard @@ -1,7 +1,7 @@ - + - + @@ -943,7 +943,7 @@ - + @@ -951,6 +951,15 @@ + + + + + + + + + @@ -1560,7 +1569,7 @@ - + @@ -1594,6 +1603,13 @@ + + + + + + + @@ -1602,7 +1618,7 @@ - + @@ -1674,6 +1690,7 @@ + diff --git a/Squirrel Designer/LayoutModel.swift b/Squirrel Designer/LayoutModel.swift index 3405e7b..6c4abcb 100644 --- a/Squirrel Designer/LayoutModel.swift +++ b/Squirrel Designer/LayoutModel.swift @@ -8,6 +8,35 @@ import AppKit +extension NSBezierPath { + + var cgPath: CGPath { + let path = CGMutablePath() + var points = [CGPoint](repeating: .zero, count: 3) + for i in 0 ..< self.elementCount { + let type = self.element(at: i, associatedPoints: &points) + + switch type { + case .moveTo: + path.move(to: points[0]) + + case .lineTo: + path.addLine(to: points[0]) + + case .curveTo: + path.addCurve(to: points[2], control1: points[0], control2: points[1]) + + case .closePath: + path.closeSubpath() + + @unknown default: + break + } + } + return path + } +} + class SquirrelLayout { static var template: String? @@ -31,6 +60,7 @@ class SquirrelLayout { var vertical = false var inlinePreedit = false var isDisplayP3 = true + var translucency = false var fonts: Array = [NSFont.userFont(ofSize: 15)!] var labelFonts = Array() @@ -184,6 +214,7 @@ class SquirrelLayout { encoded += "candidate_list_layout: \(linear ? "linear" : "stacked")\n" encoded += "text_orientation: \(vertical ? "vertical" : "horizontal")\n" encoded += "inline_preedit: \(inlinePreedit ? "true" : "false")\n" + encoded += "translucency: \(translucency)\n" if cornerRadius != 0 { encoded += "corner_radius: \(cornerRadius)\n" } @@ -343,6 +374,7 @@ class SquirrelLayout { vertical = getBool(values["vertical"]) } let inlinePreedit = getBool(values["inline_preedit"]) + let translucency = getBool(values["translucency"]) let name = values["name"] let cornerRadius = getFloat(values["corner_radius"]) let hilitedCornerRadius = getFloat(values["hilited_corner_radius"]) @@ -383,6 +415,7 @@ class SquirrelLayout { self.linear = linear ?? false self.vertical = vertical ?? false self.inlinePreedit = inlinePreedit ?? false + self.translucency = translucency ?? false self.isDisplayP3 = isDisplayP3 self.backgroundColor = backgroundColor ?? NSColor.windowBackgroundColor self.candidateTextColor = candidateTextColor ?? NSColor.controlTextColor @@ -421,6 +454,7 @@ func blendColor(foregroundColor: NSColor, backgroundColor: NSColor?) -> NSColor } class SquirrelView: NSView { + var shape: CAShapeLayer = CAShapeLayer() private var _layout: SquirrelLayout private let _text: NSTextStorage private var _highlightedRange = NSMakeRange(NSNotFound, 0) @@ -861,6 +895,7 @@ class SquirrelView: NSView { NSBezierPath.defaultLineWidth = 0 backgroundPath = drawSmoothLines(vertex(ofRect: backgroundRect), alpha: 0.3*_layout.cornerRadius, beta: 1.4*_layout.cornerRadius) + shape.path = backgroundPath?.cgPath // Nothing should extend beyond backgroundPath borderPath = backgroundPath?.copy() as? NSBezierPath borderPath?.addClip() @@ -928,6 +963,7 @@ class SquirrelPanel: NSWindow { static let kOffsetHeight: CGFloat = 5 private var _position: NSRect private let _view: SquirrelView + private let _back: NSVisualEffectView private var _preeditRange = NSMakeRange(NSNotFound, 0) private var _screenRect = NSZeroRect private var _maxHeight: CGFloat = 0 @@ -946,12 +982,22 @@ class SquirrelPanel: NSWindow { init(position: NSRect) { _position = position _view = SquirrelView(frame: position) + let blurView = NSVisualEffectView() + blurView.blendingMode = .behindWindow + blurView.material = .hudWindow + blurView.state = .active + blurView.wantsLayer = true + blurView.layer!.mask = _view.shape + _back = blurView super.init(contentRect: position, styleMask: .borderless, backing: .buffered, defer: true) self.alphaValue = 1 self.hasShadow = true self.isOpaque = false self.backgroundColor = .clear - self.contentView = _view + let contentView = NSView() + self.contentView = contentView + contentView.addSubview(_back) + contentView.addSubview(_view) self.isMovableByWindowBackground = true } @@ -1068,16 +1114,23 @@ class SquirrelPanel: NSWindow { if NSMinY(windowRect) < NSMinY(_screenRect) { windowRect.origin.y = NSMinY(_screenRect) } + self.alphaValue = self.layout.alpha + self.setFrame(windowRect, display: true) // rotate the view, the core in vertical mode! if self.layout.vertical { - _view.boundsRotation = 90.0 - _view.setBoundsOrigin(NSMakePoint(0, windowRect.size.width)) + self.contentView?.boundsRotation = -90.0 + self.contentView?.setBoundsOrigin(NSMakePoint(0, windowRect.size.width)) } else { - _view.boundsRotation = 0 - _view.setBoundsOrigin(NSMakePoint(0, 0)) + self.contentView?.boundsRotation = 0 + self.contentView?.setBoundsOrigin(NSMakePoint(0, 0)) + } + _view.frame = _view.superview!.bounds + if layout.translucency { + _back.frame = _back.superview!.bounds + _back.isHidden = false + } else { + _back.isHidden = true } - self.alphaValue = self.layout.alpha - self.setFrame(windowRect, display: true) self.invalidateShadow() self.orderFront(nil) self._visible = true diff --git a/Squirrel Designer/ViewController.swift b/Squirrel Designer/ViewController.swift index 093be4d..ebc604a 100644 --- a/Squirrel Designer/ViewController.swift +++ b/Squirrel Designer/ViewController.swift @@ -89,6 +89,7 @@ class ViewController: NSViewController { @IBOutlet weak var hilitedLabelTextColorToggle: NSSwitch! @IBOutlet weak var hilitedLabelTextColorPicker: NSColorWell! @IBOutlet weak var colorSpacePicker: NSPopUpButton! + @IBOutlet weak var translucencyToggle: NSSwitch! @IBOutlet weak var borderHeightField: NSTextField! @IBOutlet weak var borderWidthField: NSTextField! @@ -359,6 +360,10 @@ class ViewController: NSViewController { } preview.layout = layout } + @IBAction func translucencyToggled(_ sender: Any) { + layout.translucency = translucencyToggle.state == .on + preview.layout = layout + } @IBAction func candidateListLayoutToggled(_ sender: Any) { layout.linear = candidateListLayoutSwitch.selectedSegment == 1 @@ -853,6 +858,7 @@ class ViewController: NSViewController { hilitedLabelTextColorPicker.color = blendColor(foregroundColor: hilitedCandidateTextColorPicker.color, backgroundColor: hilitedCandidateBackColorPicker.color) layout.highlightedCandidateLabelColor = hilitedLabelTextColorPicker.color } + translucencyToggle.state = layout.translucency ? .on : .off borderHeightField.stringValue = "\(layout.borderHeight)" borderWidthField.stringValue = "\(layout.borderWidth)" diff --git a/Squirrel Designer/zh-Hans.lproj/Main.strings b/Squirrel Designer/zh-Hans.lproj/Main.strings index 3486870..313f2bf 100644 --- a/Squirrel Designer/zh-Hans.lproj/Main.strings +++ b/Squirrel Designer/zh-Hans.lproj/Main.strings @@ -148,6 +148,9 @@ /* Class = "NSTextFieldCell"; title = "Colorspace"; ObjectID = "GFQ-yL-V2f"; */ "GFQ-yL-V2f.title" = "色空间"; +/* Class = "NSTextFieldCell"; title = "Translucency "; ObjectID = "pT7-cp-v6P"; */ +"pT7-cp-v6P.title" = "磨砂"; + /* Class = "NSMenuItem"; title = "Use Default"; ObjectID = "GUa-eO-cwY"; */ "GUa-eO-cwY.title" = "默认"; diff --git a/Squirrel Designer/zh-Hant.lproj/Main.strings b/Squirrel Designer/zh-Hant.lproj/Main.strings index 980812d..3d0d4c5 100644 --- a/Squirrel Designer/zh-Hant.lproj/Main.strings +++ b/Squirrel Designer/zh-Hant.lproj/Main.strings @@ -148,6 +148,9 @@ /* Class = "NSTextFieldCell"; title = "Colorspace"; ObjectID = "GFQ-yL-V2f"; */ "GFQ-yL-V2f.title" = "色空間"; +/* Class = "NSTextFieldCell"; title = "Translucency "; ObjectID = "pT7-cp-v6P"; */ +"pT7-cp-v6P.title" = "磨砂"; + /* Class = "NSMenuItem"; title = "Use Default"; ObjectID = "GUa-eO-cwY"; */ "GUa-eO-cwY.title" = "默認";