diff --git a/Squirrel.xcodeproj/project.pbxproj b/Squirrel.xcodeproj/project.pbxproj index 2580129f2..6323f17a3 100644 --- a/Squirrel.xcodeproj/project.pbxproj +++ b/Squirrel.xcodeproj/project.pbxproj @@ -653,7 +653,7 @@ CODE_SIGN_IDENTITY = "-"; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 0.16.2u; + CURRENT_PROJECT_VERSION = 0.18.0u; DEAD_CODE_STRIPPING = YES; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -709,7 +709,7 @@ CLANG_ENABLE_OBJC_ARC = YES; CODE_SIGN_IDENTITY = "-"; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 0.16.2u; + CURRENT_PROJECT_VERSION = 0.18.0u; DEAD_CODE_STRIPPING = YES; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", diff --git a/SquirrelConfig.hh b/SquirrelConfig.hh index 8c56a374b..62f5813f8 100644 --- a/SquirrelConfig.hh +++ b/SquirrelConfig.hh @@ -4,15 +4,15 @@ __attribute__((objc_direct_members)) @interface SquirrelOptionSwitcher : NSObject -@property(nonatomic, strong, readonly, nonnull) NSString* schemaId; -@property(nonatomic, strong, readonly, nonnull) NSString* currentScriptVariant; -@property(nonatomic, strong, readonly, nonnull) NSSet* optionNames; -@property(nonatomic, strong, readonly, nonnull) NSSet* optionStates; -@property(nonatomic, strong, readonly, nonnull) +@property(nonatomic, readonly, strong, nonnull) NSString* schemaId; +@property(nonatomic, readonly, strong, nonnull) NSString* currentScriptVariant; +@property(nonatomic, readonly, strong, nonnull) NSSet* optionNames; +@property(nonatomic, readonly, strong, nonnull) NSSet* optionStates; +@property(nonatomic, readonly, strong, nonnull) NSDictionary* scriptVariantOptions; -@property(nonatomic, strong, readonly, nonnull) +@property(nonatomic, readonly, strong, nonnull) NSMutableDictionary* switcher; -@property(nonatomic, strong, readonly, nonnull) +@property(nonatomic, readonly, strong, nonnull) NSDictionary*>* optionGroups; - (instancetype _Nonnull) diff --git a/SquirrelInputController.hh b/SquirrelInputController.hh index 22952bf36..edf5cb523 100644 --- a/SquirrelInputController.hh +++ b/SquirrelInputController.hh @@ -32,13 +32,13 @@ typedef NS_ENUM(NSUInteger, SquirrelIndex) { kVoidSymbol = 0xffffff // XK_VoidSymbol }; -@property(nonatomic, weak, readonly, nullable, direct, class) +@property(nonatomic, readonly, weak, nullable, direct, class) SquirrelInputController* currentController; -@property(nonatomic, strong, readonly, nonnull) +@property(nonatomic, readonly, strong, nonnull) NSAppearance* viewEffectiveAppearance API_AVAILABLE(macos(10.14)); -@property(nonatomic, strong, readonly, nonnull, direct) +@property(nonatomic, readonly, strong, nonnull, direct) NSMutableArray* candidateTexts; -@property(nonatomic, strong, readonly, nonnull, direct) +@property(nonatomic, readonly, strong, nonnull, direct) NSMutableArray* candidateComments; - (void)moveCursor:(NSUInteger)cursorPosition diff --git a/SquirrelPanel.hh b/SquirrelPanel.hh index 9e9e797e8..92f554d77 100644 --- a/SquirrelPanel.hh +++ b/SquirrelPanel.hh @@ -22,10 +22,10 @@ @property(nonatomic, direct) NSUInteger sectionNum; // position of the text input I-beam cursor on screen. @property(nonatomic, direct) NSRect IbeamRect; -@property(nonatomic, strong, readonly, nullable) NSScreen* screen; +@property(nonatomic, readonly, strong, nullable) NSScreen* screen; // Status message before pop-up is displayed; nil before normal panel is // displayed -@property(nonatomic, strong, readonly, nullable, direct) +@property(nonatomic, readonly, strong, nullable, direct) NSString* statusMessage; // Store switch options that change style (color theme) settings @property(nonatomic, strong, nonnull, direct) diff --git a/SquirrelPanel.mm b/SquirrelPanel.mm index 547b1c56c..18f1167fe 100644 --- a/SquirrelPanel.mm +++ b/SquirrelPanel.mm @@ -341,10 +341,10 @@ + (NSColorSpace*)labColorSpace { @interface NSColor (semanticColors) -@property(nonatomic, strong, readonly, nonnull, direct, class) +@property(nonatomic, readonly, strong, nonnull, direct, class) NSColor* accentColor; -@property(nonatomic, strong, readonly, nonnull, direct) NSColor* hooverColor; -@property(nonatomic, strong, readonly, nonnull, direct) NSColor* disabledColor; +@property(nonatomic, readonly, strong, nonnull, direct) NSColor* hooverColor; +@property(nonatomic, readonly, strong, nonnull, direct) NSColor* disabledColor; @end @@ -503,25 +503,26 @@ typedef NS_CLOSED_ENUM(NSUInteger, SquirrelStatusMessageType) { __attribute__((objc_direct_members)) @interface SquirrelTheme : NSObject -@property(nonatomic, strong, readonly, nonnull) NSColor* backColor; -@property(nonatomic, strong, readonly, nonnull) NSColor* preeditForeColor; -@property(nonatomic, strong, readonly, nonnull) NSColor* textForeColor; -@property(nonatomic, strong, readonly, nonnull) NSColor* commentForeColor; -@property(nonatomic, strong, readonly, nonnull) NSColor* labelForeColor; -@property(nonatomic, strong, readonly, nonnull) +@property(nonatomic, readonly, strong, nonnull) NSColor* backColor; +@property(nonatomic, readonly, strong, nonnull) NSColor* preeditForeColor; +@property(nonatomic, readonly, strong, nonnull) NSColor* textForeColor; +@property(nonatomic, readonly, strong, nonnull) NSColor* commentForeColor; +@property(nonatomic, readonly, strong, nonnull) NSColor* labelForeColor; +@property(nonatomic, readonly, strong, nonnull) NSColor* hilitedPreeditForeColor; -@property(nonatomic, strong, readonly, nonnull) NSColor* hilitedTextForeColor; -@property(nonatomic, strong, readonly, nonnull) +@property(nonatomic, readonly, strong, nonnull) NSColor* hilitedTextForeColor; +@property(nonatomic, readonly, strong, nonnull) NSColor* hilitedCommentForeColor; -@property(nonatomic, strong, readonly, nonnull) NSColor* hilitedLabelForeColor; -@property(nonatomic, strong, readonly, nullable) NSColor* dimmedLabelForeColor; -@property(nonatomic, strong, readonly, nullable) +@property(nonatomic, readonly, strong, nonnull) NSColor* hilitedLabelForeColor; +@property(nonatomic, readonly, strong, nullable) NSColor* dimmedLabelForeColor; +@property(nonatomic, readonly, strong, nullable) NSColor* hilitedCandidateBackColor; -@property(nonatomic, strong, readonly, nullable) +@property(nonatomic, readonly, strong, nullable) NSColor* hilitedPreeditBackColor; -@property(nonatomic, strong, readonly, nullable) NSColor* preeditBackColor; -@property(nonatomic, strong, readonly, nullable) NSColor* borderColor; -@property(nonatomic, strong, readonly, nullable) NSImage* backImage; +@property(nonatomic, readonly, strong, nullable) NSColor* candidateBackColor; +@property(nonatomic, readonly, strong, nullable) NSColor* preeditBackColor; +@property(nonatomic, readonly, strong, nullable) NSColor* borderColor; +@property(nonatomic, readonly, strong, nullable) NSImage* backImage; @property(nonatomic, readonly) NSSize borderInsets; @property(nonatomic, readonly) CGFloat cornerRadius; @@ -531,6 +532,7 @@ @interface SquirrelTheme : NSObject @property(nonatomic, readonly) CGFloat preeditSpacing; @property(nonatomic, readonly) CGFloat opacity; @property(nonatomic, readonly) CGFloat lineLength; +@property(nonatomic, readonly) CGFloat shadowSize; @property(nonatomic, readonly) float translucency; @property(nonatomic, readonly) BOOL showPaging; @property(nonatomic, readonly) BOOL rememberSize; @@ -540,58 +542,58 @@ @interface SquirrelTheme : NSObject @property(nonatomic, readonly) BOOL inlinePreedit; @property(nonatomic, readonly) BOOL inlineCandidate; -@property(nonatomic, strong, readonly, nonnull) +@property(nonatomic, readonly, strong, nonnull) NSDictionary* textAttrs; -@property(nonatomic, strong, readonly, nonnull) +@property(nonatomic, readonly, strong, nonnull) NSDictionary* labelAttrs; -@property(nonatomic, strong, readonly, nonnull) +@property(nonatomic, readonly, strong, nonnull) NSDictionary* commentAttrs; -@property(nonatomic, strong, readonly, nonnull) +@property(nonatomic, readonly, strong, nonnull) NSDictionary* preeditAttrs; -@property(nonatomic, strong, readonly, nonnull) +@property(nonatomic, readonly, strong, nonnull) NSDictionary* pagingAttrs; -@property(nonatomic, strong, readonly, nonnull) +@property(nonatomic, readonly, strong, nonnull) NSDictionary* statusAttrs; -@property(nonatomic, strong, readonly, nonnull) +@property(nonatomic, readonly, strong, nonnull) NSParagraphStyle* candidateParagraphStyle; -@property(nonatomic, strong, readonly, nonnull) +@property(nonatomic, readonly, strong, nonnull) NSParagraphStyle* preeditParagraphStyle; -@property(nonatomic, strong, readonly, nonnull) +@property(nonatomic, readonly, strong, nonnull) NSParagraphStyle* statusParagraphStyle; -@property(nonatomic, strong, readonly, nonnull) +@property(nonatomic, readonly, strong, nonnull) NSParagraphStyle* pagingParagraphStyle; -@property(nonatomic, strong, readonly, nullable) +@property(nonatomic, readonly, strong, nullable) NSParagraphStyle* truncatedParagraphStyle; -@property(nonatomic, strong, readonly, nonnull) NSAttributedString* separator; -@property(nonatomic, strong, readonly, nonnull) +@property(nonatomic, readonly, strong, nonnull) NSAttributedString* separator; +@property(nonatomic, readonly, strong, nonnull) NSAttributedString* symbolDeleteFill; -@property(nonatomic, strong, readonly, nonnull) +@property(nonatomic, readonly, strong, nonnull) NSAttributedString* symbolDeleteStroke; -@property(nonatomic, strong, readonly, nullable) +@property(nonatomic, readonly, strong, nullable) NSAttributedString* symbolBackFill; -@property(nonatomic, strong, readonly, nullable) +@property(nonatomic, readonly, strong, nullable) NSAttributedString* symbolBackStroke; -@property(nonatomic, strong, readonly, nullable) +@property(nonatomic, readonly, strong, nullable) NSAttributedString* symbolForwardFill; -@property(nonatomic, strong, readonly, nullable) +@property(nonatomic, readonly, strong, nullable) NSAttributedString* symbolForwardStroke; -@property(nonatomic, strong, readonly, nullable) +@property(nonatomic, readonly, strong, nullable) NSAttributedString* symbolCompress; -@property(nonatomic, strong, readonly, nullable) +@property(nonatomic, readonly, strong, nullable) NSAttributedString* symbolExpand; -@property(nonatomic, strong, readonly, nullable) NSAttributedString* symbolLock; +@property(nonatomic, readonly, strong, nullable) NSAttributedString* symbolLock; -@property(nonatomic, strong, readonly, nonnull) NSArray* labels; -@property(nonatomic, strong, readonly, nonnull) +@property(nonatomic, readonly, strong, nonnull) NSArray* labels; +@property(nonatomic, readonly, strong, nonnull) NSAttributedString* candidateTemplate; -@property(nonatomic, strong, readonly, nonnull) +@property(nonatomic, readonly, strong, nonnull) NSAttributedString* candidateHilitedTemplate; -@property(nonatomic, strong, readonly, nullable) +@property(nonatomic, readonly, strong, nullable) NSAttributedString* candidateDimmedTemplate; -@property(nonatomic, strong, readonly, nonnull) NSString* selectKeys; -@property(nonatomic, strong, readonly, nonnull) NSString* candidateFormat; -@property(nonatomic, strong, readonly, nonnull) NSString* scriptVariant; +@property(nonatomic, readonly, strong, nonnull) NSString* selectKeys; +@property(nonatomic, readonly, strong, nonnull) NSString* candidateFormat; +@property(nonatomic, readonly, strong, nonnull) NSString* scriptVariant; @property(nonatomic, readonly) SquirrelStatusMessageType statusMessageType; @property(nonatomic, readonly) NSUInteger pageSize; @property(nonatomic, readonly) SquirrelAppearance appearance; @@ -1368,11 +1370,14 @@ - (void)updateWithConfig:(SquirrelConfig*)config [config getOptionalDoubleForOption:@"style/base_offset"]; NSNumber* lineLength = [config getOptionalDoubleForOption:@"style/line_length"]; + NSNumber* shadowSize = + [config getOptionalDoubleForOption:@"style/shadow_size"]; /*** CHROMATICS ***/ NSColor* backColor; NSColor* borderColor; NSColor* preeditBackColor; NSColor* preeditForeColor; + NSColor* candidateBackColor; NSColor* textForeColor; NSColor* commentForeColor; NSColor* labelForeColor; @@ -1440,6 +1445,10 @@ - (void)updateWithConfig:(SquirrelConfig*)config [config getColorForOption:[prefix stringByAppendingString:@"/text_color"]] ?: preeditForeColor; + candidateBackColor = + [config getColorForOption: + [prefix stringByAppendingString:@"/candidate_back_color"]] + ?: candidateBackColor; textForeColor = [config getColorForOption: [prefix stringByAppendingString:@"/candidate_text_color"]] @@ -1587,6 +1596,10 @@ - (void)updateWithConfig:(SquirrelConfig*)config lineLength = [config getOptionalDoubleForOption: [prefix stringByAppendingString:@"/line_length"]] ?: lineLength; + shadowSize = [config getOptionalDoubleForOption: + [prefix stringByAppendingString:@"/shadow_size"] + applyConstraint:positive] + ?: shadowSize; } /*** TYPOGRAPHY refinement ***/ @@ -1640,8 +1653,6 @@ - (void)updateWithConfig:(SquirrelConfig*)config CGFloat fullWidth = ceil( [kFullWidthSpace sizeWithAttributes:@{NSFontAttributeName : commentFont}] .width); - spacing = spacing ?: @0; - lineSpacing = lineSpacing ?: @0; NSMutableParagraphStyle* preeditParagraphStyle = _preeditParagraphStyle.mutableCopy; @@ -1769,7 +1780,6 @@ - (void)updateWithConfig:(SquirrelConfig*)config pagingAttrs[NSVerticalGlyphFormAttributeName] = @NO; /*** CHROMATICS refinement ***/ - translucency = translucency ?: @0; if (@available(macOS 10.14, *)) { if (translucency.floatValue > 0.001f && !isNative && backColor != nil && (_appearance == kDarkAppearance ? backColor.lStarComponent > 0.6 @@ -1782,6 +1792,8 @@ - (void)updateWithConfig:(SquirrelConfig*)config colorByInvertingLuminanceToExtent:kStandardColorInversion]; preeditForeColor = [preeditForeColor colorByInvertingLuminanceToExtent:kStandardColorInversion]; + candidateBackColor = [candidateBackColor + colorByInvertingLuminanceToExtent:kStandardColorInversion]; textForeColor = [textForeColor colorByInvertingLuminanceToExtent:kStandardColorInversion]; commentForeColor = [commentForeColor @@ -1854,6 +1866,7 @@ - (void)updateWithConfig:(SquirrelConfig*)config _lineLength = lineLength.doubleValue > 0.1 ? fmax(ceil(lineLength.doubleValue), fullWidth * 5) : 0.0; + _shadowSize = shadowSize.doubleValue; _translucency = translucency.floatValue; _showPaging = showPaging.boolValue; _rememberSize = rememberSize.boolValue; @@ -1864,8 +1877,8 @@ - (void)updateWithConfig:(SquirrelConfig*)config _inlineCandidate = inlineCandidate.boolValue; _textAttrs = textAttrs; - _labelAttrs = labelAttrs; _commentAttrs = commentAttrs; + _labelAttrs = labelAttrs; _preeditAttrs = preeditAttrs; _pagingAttrs = pagingAttrs; _statusAttrs = statusAttrs; @@ -1877,15 +1890,16 @@ - (void)updateWithConfig:(SquirrelConfig*)config _backImage = backImage; _backColor = backColor; - _preeditBackColor = preeditBackColor; - _hilitedPreeditBackColor = hilitedPreeditBackColor; - _hilitedCandidateBackColor = hilitedCandidateBackColor; _borderColor = borderColor; + _preeditBackColor = preeditBackColor; _preeditForeColor = preeditForeColor; + _candidateBackColor = candidateBackColor; _textForeColor = textForeColor; _commentForeColor = commentForeColor; _labelForeColor = labelForeColor; + _hilitedPreeditBackColor = hilitedPreeditBackColor; _hilitedPreeditForeColor = hilitedPreeditForeColor; + _hilitedCandidateBackColor = hilitedCandidateBackColor; _hilitedTextForeColor = hilitedTextForeColor; _hilitedCommentForeColor = hilitedCommentForeColor; _hilitedLabelForeColor = hilitedLabelForeColor; @@ -2463,10 +2477,12 @@ @interface SquirrelView : NSView CAShapeLayer* functionButtonLayer; @property(nonatomic, readonly, strong, nonnull) CALayer* logoLayer; @property(nonatomic, readonly, strong, nonnull) CAShapeLayer* documentLayer; -@property(nonatomic, readonly, strong, nonnull) - CAShapeLayer* hilitedCandidateLayer; @property(nonatomic, readonly, strong, nonnull) CAShapeLayer* activePageLayer; @property(nonatomic, readonly, strong, nonnull) CAShapeLayer* gridLayer; +@property(nonatomic, readonly, strong, nonnull) + CAShapeLayer* nonHilitedCandidateLayer; +@property(nonatomic, readonly, strong, nonnull) + CAShapeLayer* hilitedCandidateLayer; @property(nonatomic, readonly, nullable) SquirrelTabularIndex* tabularIndices; @property(nonatomic, readonly, nullable) SquirrelTextPolygon* candidatePolygons; @property(nonatomic, readonly, nullable) NSRectArray sectionRects; @@ -2650,12 +2666,14 @@ - (instancetype)init { _documentLayer = CAShapeLayer.alloc.init; _activePageLayer = CAShapeLayer.alloc.init; _gridLayer = CAShapeLayer.alloc.init; + _nonHilitedCandidateLayer = CAShapeLayer.alloc.init; _hilitedCandidateLayer = CAShapeLayer.alloc.init; _documentLayer.fillRule = kCAFillRuleEvenOdd; _gridLayer.lineWidth = 1.0; [_documentView.layer addSublayer:_documentLayer]; [_documentLayer addSublayer:_activePageLayer]; [_documentView.layer addSublayer:_gridLayer]; + [_documentView.layer addSublayer:_nonHilitedCandidateLayer]; [_documentView.layer addSublayer:_hilitedCandidateLayer]; } return self; @@ -2678,8 +2696,23 @@ - (void)updateColors { } else { _hilitedPreeditLayer.hidden = YES; } + if (_theme.candidateBackColor != nil) { + _nonHilitedCandidateLayer.fillColor = _theme.candidateBackColor.CGColor; + } else { + _nonHilitedCandidateLayer.hidden = YES; + } if (_theme.hilitedCandidateBackColor != nil) { _hilitedCandidateLayer.fillColor = _theme.hilitedCandidateBackColor.CGColor; + if (_theme.shadowSize > 0.1) { + _hilitedCandidateLayer.shadowOffset = + CGSizeMake(_theme.shadowSize, _theme.shadowSize); + // _hilitedCandidateLayer.shadowRadius = _theme.shadowSize * 0.3; + _hilitedCandidateLayer.shadowOpacity = 1.0; + // _hilitedCandidateLayer.shadowColor = + // [_theme.hilitedCandidateBackColor shadowWithLevel:0.3].CGColor; + } else { + _hilitedCandidateLayer.shadowOpacity = 0.0; + } } else { _hilitedCandidateLayer.hidden = YES; } @@ -2951,8 +2984,8 @@ - (SquirrelTextPolygon)textPolygonForRange:(NSRange)charRange inView:view]; NSRect __block headLineRect = NSZeroRect; NSRect __block tailLineRect = NSZeroRect; - NSTextRange __block* headLineRange; - NSTextRange __block* tailLineRange; + NSTextRange* __block headLineRange; + NSTextRange* __block tailLineRange; [layoutManager enumerateTextSegmentsInRange:textRange type:NSTextLayoutManagerSegmentTypeStandard @@ -3566,7 +3599,9 @@ - (void)updateLayer { _candidatePolygons = NULL; _sectionRects = NULL; _tabularIndices = NULL; - NSBezierPath *candidatesPath, *documentPath, *gridPath; + NSBezierPath* candidatesPath; + NSBezierPath* documentPath; + NSBezierPath* gridPath; if (!_scrollView.hidden) { _candidatesRect.size.width = NSWidth(backgroundRect); _candidatesRect = [self @@ -3740,7 +3775,8 @@ - (void)updateLayer { outerCornerRadius - fmin(_theme.borderInsets.width, _theme.borderInsets.height), NSHeight(backgroundRect) * 0.5); - NSBezierPath *panelPath, *backgroundPath; + NSBezierPath* panelPath; + NSBezierPath* backgroundPath; if (!_theme.linear || _pagingView.hidden) { panelPath = squirclePath(panelRect, outerCornerRadius); backgroundPath = squirclePath(backgroundRect, innerCornerRadius); @@ -3831,11 +3867,27 @@ - (void)updateLayer { } else { _gridLayer.hidden = YES; } + CGFloat cornerRadius = + fmin(_theme.hilitedCornerRadius, + _theme.candidateParagraphStyle.minimumLineHeight * 0.5); + if (_theme.candidateBackColor != nil) { + NSBezierPath* nonHilitedCandidatePath = NSBezierPath.bezierPath; + for (NSUInteger i = 0; i < _candidateCount; ++i) { + if (i != _hilitedCandidate) + [nonHilitedCandidatePath + appendBezierPath:_theme.linear + ? squirclePath(_candidatePolygons[i], + cornerRadius) + : squirclePath(_candidatePolygons[i].body, + cornerRadius)]; + } + _nonHilitedCandidateLayer.path = nonHilitedCandidatePath.quartzPath; + _nonHilitedCandidateLayer.hidden = NO; + } else { + _nonHilitedCandidateLayer.hidden = YES; + } if (_hilitedCandidate != NSNotFound && _theme.hilitedCandidateBackColor != nil) { - CGFloat cornerRadius = - fmin(_theme.hilitedCornerRadius, - _theme.candidateParagraphStyle.minimumLineHeight * 0.5); NSBezierPath* hilitedCandidatePath = _theme.linear ? squirclePath(_candidatePolygons[_hilitedCandidate], @@ -3894,8 +3946,8 @@ - (SquirrelIndex)getIndexFromMouseSpot:(NSPoint)spot { This class makes system-alike tooltips above SquirrelPanel */ @interface SquirrelToolTip : NSWindow -@property(nonatomic, strong, readonly, nullable, direct) NSTimer* displayTimer; -@property(nonatomic, strong, readonly, nullable, direct) NSTimer* hideTimer; +@property(nonatomic, readonly, strong, nullable, direct) NSTimer* displayTimer; +@property(nonatomic, readonly, strong, nullable, direct) NSTimer* hideTimer; - (void)showWithToolTip:(NSString* _Nullable)toolTip withDelay:(BOOL)delay __attribute__((objc_direct)); @@ -4019,7 +4071,7 @@ - (void)hide { #pragma mark - Panel window, dealing with text content and mouse interactions @implementation SquirrelPanel { - SquirrelInputController __weak* _inputController; + SquirrelInputController* __weak _inputController; // Squirrel panel layouts NSVisualEffectView* _back; SquirrelToolTip* _toolTip;