diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..da2229b --- /dev/null +++ b/.gitignore @@ -0,0 +1,60 @@ +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## Build generated +build/ +DerivedData/ + +## Various settings +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata/ + +## Other +*.moved-aside +*.xcuserstate + +## Obj-C/Swift specific +*.hmap +*.ipa +*.dSYM.zip +*.dSYM + +# CocoaPods +# +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control +# +Pods/ + +# Carthage +# +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +Carthage/Build + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the +# screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md + +fastlane/report.xml +fastlane/screenshots + +#Code Injection +# +# After new code Injection tools there's a generated folder /iOSInjectionProject +# https://github.com/johnno1962/injectionforxcode + +iOSInjectionProject/ diff --git a/VHGithubNotifier.xcodeproj/project.pbxproj b/VHGithubNotifier.xcodeproj/project.pbxproj index 7d10b72..47410b6 100644 --- a/VHGithubNotifier.xcodeproj/project.pbxproj +++ b/VHGithubNotifier.xcodeproj/project.pbxproj @@ -263,6 +263,7 @@ 37CB06001E1C0CC700E9B924 /* VHGithubNotifierManager+ChartDataProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 37CB05FF1E1C0CC700E9B924 /* VHGithubNotifierManager+ChartDataProvider.m */; }; 37E7CCFB1E5C576D00BA8BA9 /* VHStateView.m in Sources */ = {isa = PBXBuildFile; fileRef = 37E7CCFA1E5C576D00BA8BA9 /* VHStateView.m */; }; 37E7CD011E5C5D2D00BA8BA9 /* VHStateView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 37E7CD001E5C5D2D00BA8BA9 /* VHStateView.xib */; }; + 5269F87E1EB7D1BC00BAF757 /* VHPieChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5269F87D1EB7D1BC00BAF757 /* VHPieChartView.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -674,6 +675,7 @@ 37E7CCF91E5C576D00BA8BA9 /* VHStateView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VHStateView.h; sourceTree = ""; }; 37E7CCFA1E5C576D00BA8BA9 /* VHStateView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VHStateView.m; sourceTree = ""; }; 37E7CD001E5C5D2D00BA8BA9 /* VHStateView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = VHStateView.xib; sourceTree = ""; }; + 5269F87D1EB7D1BC00BAF757 /* VHPieChartView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VHPieChartView.swift; sourceTree = ""; }; A9FD0823EF354958CE567028 /* libPods-VHGithubNotifier.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-VHGithubNotifier.a"; sourceTree = BUILT_PRODUCTS_DIR; }; F12D56CE52FBE25F772313B8 /* Pods-VHGithubNotifier.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-VHGithubNotifier.release.xcconfig"; path = "Pods/Target Support Files/Pods-VHGithubNotifier/Pods-VHGithubNotifier.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -1322,6 +1324,7 @@ 373EAB2A1E7031A0005B5E86 /* VHContributionChartView.h */, 373EAB2B1E7031A0005B5E86 /* VHContributionChartView.m */, 373EAB181E6EFE69005B5E86 /* VHVisualEffectView.swift */, + 5269F87D1EB7D1BC00BAF757 /* VHPieChartView.swift */, ); path = View; sourceTree = ""; @@ -1745,6 +1748,7 @@ 373187771E61D95200926F4F /* PieChartRenderer.swift in Sources */, 373BA70F1E6ABD6F00653C92 /* VHGithubNotifierManager+Trend.m in Sources */, 373187841E61D95200926F4F /* XAxisRendererHorizontalBarChart.swift in Sources */, + 5269F87E1EB7D1BC00BAF757 /* VHPieChartView.swift in Sources */, 373187751E61D95200926F4F /* LineRadarRenderer.swift in Sources */, 3731872E1E61D95200926F4F /* CandleChartDataSet.swift in Sources */, 3731871C1E61D95200926F4F /* IMarker.swift in Sources */, diff --git a/VHGithubNotifier/AppDelegate.m b/VHGithubNotifier/AppDelegate.m index e0905f9..b3ce4c1 100644 --- a/VHGithubNotifier/AppDelegate.m +++ b/VHGithubNotifier/AppDelegate.m @@ -120,12 +120,12 @@ - (void)showMenu else { NOTIFICATION_POST(kNotifyWindowWillAppear); - NSRect statusItemFrame = [[self.statusItem.view window] convertRectToScreen:self.statusItem.view.frame]; - [self.menuWindow updateArrowWithStatusItemCenterX:statusItemFrame.origin.x + statusItemFrame.size.width / 2 - withStatusItemFrame:statusItemFrame]; - + + [self.menuWindow updateArrowWithStatusItem:self.statusItem]; + [self.menuWindow setAlphaValue:0.0]; [self.menuWindow makeKeyAndOrderFront:self]; + [self.menuWindow setCollectionBehavior:NSWindowCollectionBehaviorCanJoinAllSpaces]; [[NSAnimationContext currentContext] setDuration:0.15]; [[self.menuWindow animator] setAlphaValue:1.0]; } diff --git a/VHGithubNotifier/Model/Manager/VHGithubNotifierManager+ChartDataProvider.h b/VHGithubNotifier/Model/Manager/VHGithubNotifierManager+ChartDataProvider.h index d816994..7c39949 100644 --- a/VHGithubNotifier/Model/Manager/VHGithubNotifierManager+ChartDataProvider.h +++ b/VHGithubNotifier/Model/Manager/VHGithubNotifierManager+ChartDataProvider.h @@ -7,7 +7,7 @@ // #import "VHGithubNotifierManager.h" -#import "VHGithubNotifier-Bridging-Header.h" +#import "VHGithubNotifier-Swift.h" @interface VHGithubNotifierManager (ChartDataProvider) diff --git a/VHGithubNotifier/Model/VHRepository.h b/VHGithubNotifier/Model/VHRepository.h index d0b69f8..8a88ca9 100644 --- a/VHGithubNotifier/Model/VHRepository.h +++ b/VHGithubNotifier/Model/VHRepository.h @@ -8,7 +8,7 @@ #import #import "VHRecord.h" -#import "VHGithubNotifier-Bridging-Header.h" +#import "VHGithubNotifier-Swift.h" @interface VHRepository : RLMObject diff --git a/VHGithubNotifier/Utils/VHDateValueFormatter.h b/VHGithubNotifier/Utils/VHDateValueFormatter.h index 13b5db6..753f182 100644 --- a/VHGithubNotifier/Utils/VHDateValueFormatter.h +++ b/VHGithubNotifier/Utils/VHDateValueFormatter.h @@ -6,7 +6,7 @@ // Copyright © 2017年 黄伟平. All rights reserved. // -#import "VHGithubNotifier-Bridging-Header.h" +#import "VHGithubNotifier-Swift.h" @interface VHDateValueFormatter : NSObject diff --git a/VHGithubNotifier/Utils/VHUtils.h b/VHGithubNotifier/Utils/VHUtils.h index 7862ff3..2af7e68 100644 --- a/VHGithubNotifier/Utils/VHUtils.h +++ b/VHGithubNotifier/Utils/VHUtils.h @@ -6,7 +6,7 @@ // Copyright © 2016年 黄伟平. All rights reserved. // -#import "VHGithubNotifier-Bridging-Header.h" +#import "VHGithubNotifier-Swift.h" @interface VHUtils : NSObject diff --git a/VHGithubNotifier/VC/VHPieVC.m b/VHGithubNotifier/VC/VHPieVC.m index 2d54d68..43135b4 100644 --- a/VHGithubNotifier/VC/VHPieVC.m +++ b/VHGithubNotifier/VC/VHPieVC.m @@ -8,7 +8,7 @@ #import "VHPieVC.h" #import "AFURLSessionManager.h" -#import "VHGithubNotifier-Bridging-Header.h" +#import "VHGithubNotifier-Swift.h" #import "VHGithubNotifierManager+ChartDataProvider.h" #import "VHGithubNotifierManager+UserDefault.h" #import "VHUtils.h" @@ -17,7 +17,7 @@ @interface VHPieVC () -@property (nonatomic, strong) PieChartView *pieChart; +@property (nonatomic, strong) VHPieChartView *pieChart; @property (weak) IBOutlet VHCursorButton *openUrlButton; @property (nonatomic, strong) NSString *highlightedRepositoryName; @@ -30,7 +30,7 @@ @implementation VHPieVC - (void)viewDidLoad { [super viewDidLoad]; - self.pieChart = [[PieChartView alloc] initWithFrame:self.view.bounds]; + self.pieChart = [[VHPieChartView alloc] initWithFrame:self.view.bounds]; self.pieChart.extraLeftOffset = 30; self.pieChart.extraRightOffset = 30; self.pieChart.highlightPerTapEnabled = YES; @@ -74,10 +74,10 @@ - (void)onNotifyRepositoriesLoadedSuccessfully:(NSNotification *)notification [self.pieChart notifyDataSetChanged]; [self.pieChart highlightValue:nil]; self.openUrlButton.hidden = YES; - + // update total star number [self updateCenterText]; - + // update description text [self updateDescriptionText]; @@ -107,6 +107,7 @@ - (void)onNotifyTabInTabViewControllerChanged:(NSNotification *)notification - (void)onNotifyMinimumStarNumberInPieChanged:(NSNotification *)notification { + [[VHGithubNotifierManager sharedManager] updateUserRepositoriesPieData]; [self onNotifyRepositoriesLoadedSuccessfully:nil]; } @@ -116,6 +117,7 @@ - (void)chartValueSelected:(ChartViewBase * _Nonnull)chartView entry:(ChartDataE { NSString *name = ((PieChartDataEntry *)entry).label; self.highlightedRepositoryName = name; + self.pieChart.descriptionTextAlign = NSTextAlignmentRight; self.pieChart.chartDescription.text = [NSString stringWithFormat:@"Visit %@ ", name]; self.openUrlButton.hidden = NO; } @@ -163,6 +165,7 @@ - (void)updateCenterText - (void)updateDescriptionText { [self.openUrlButton setTop:self.pieChart.legend.neededHeight + 20]; + self.pieChart.descriptionTextAlign = NSTextAlignmentCenter; NSUInteger repositoryNumber = [[self.pieChart.data.dataSets firstObject] entryCount]; if (repositoryNumber == 0) { diff --git a/VHGithubNotifier/VC/VHTrendVC.m b/VHGithubNotifier/VC/VHTrendVC.m index fec1280..df30002 100644 --- a/VHGithubNotifier/VC/VHTrendVC.m +++ b/VHGithubNotifier/VC/VHTrendVC.m @@ -11,7 +11,7 @@ #import "VHGithubNotifierManager.h" #import "VHGithubNotifierManager+UserDefault.h" #import "VHGithubNotifierManager+Trend.h" -#import "VHGithubNotifier-Bridging-Header.h" +#import "VHGithubNotifier-Swift.h" #import "VHDateValueFormatter.h" #import "VHUtils.h" #import diff --git a/VHGithubNotifier/View/VHPieChartView.swift b/VHGithubNotifier/View/VHPieChartView.swift new file mode 100644 index 0000000..a543bde --- /dev/null +++ b/VHGithubNotifier/View/VHPieChartView.swift @@ -0,0 +1,52 @@ +// +// Extensions.swift +// VHGithubNotifier +// +// Created by Apollo Zhu on 4/30/17. +// Copyright © 2017 黄伟平. All rights reserved. +// + +extension Description { + + fileprivate var fontSize: CGFloat { + get { + return font.pointSize + } + set { + font = NSUIFont(name: font.fontName, size: newValue) ?? font + } + } + + fileprivate var width: CGFloat { + return text!.size(attributes: [NSFontAttributeName:font]).width + } + +} + +@objc class VHPieChartView: PieChartView { + + override func draw(_ rect: CGRect) { + if chartDescription?.textAlign == .center { + let max = bounds.width - chartDescription!.xOffset * 2 + let cur = chartDescription!.width + if cur > max { + chartDescription!.fontSize *= max / cur + } + + chartDescription!.position = + CGPoint(x: bounds.midX, + y: bounds.maxY + - legend.yOffset + - legend.neededHeight + - chartDescription!.yOffset + - chartDescription!.font.lineHeight + - 20) + } else { + chartDescription?.position = nil + } + + super.draw(rect) + } + +} + diff --git a/VHGithubNotifier/View/VHVisualEffectView.swift b/VHGithubNotifier/View/VHVisualEffectView.swift index f479953..19beee1 100644 --- a/VHGithubNotifier/View/VHVisualEffectView.swift +++ b/VHGithubNotifier/View/VHVisualEffectView.swift @@ -9,28 +9,21 @@ import Cocoa @objc class VHVisualEffectView: NSVisualEffectView { - + override init(frame frameRect: NSRect) { - self.tintColor = NSColor.init(red: 0, green: 0, blue: 0, alpha: 0); - super.init(frame:frameRect); + tintColor = .clear + super.init(frame:frameRect) } - + required init?(coder: NSCoder) { - self.tintColor = NSColor.init(red: 0, green: 0, blue: 0, alpha: 0); - super.init(coder: coder); + tintColor = .clear + super.init(coder: coder) } - + var tintColor: NSColor { - willSet { - - } didSet { - for sublayer: CALayer in self.layer!.sublayers! { - if sublayer.name == "ClearCopyLayer" { - sublayer.backgroundColor = tintColor.cgColor - break - } - } + layer?.sublayers?.first(where: { $0.name == "ClearCopyLayer" })?.backgroundColor = tintColor.cgColor } } + } diff --git a/VHGithubNotifier/Window/VHWindow.h b/VHGithubNotifier/Window/VHWindow.h index b823006..3f4c94a 100644 --- a/VHGithubNotifier/Window/VHWindow.h +++ b/VHGithubNotifier/Window/VHWindow.h @@ -21,6 +21,6 @@ - (instancetype)initWithStatusItem:(NSStatusItem *)statusBarButton withDelegate:(id)delegate; -- (void)updateArrowWithStatusItemCenterX:(CGFloat)centerX withStatusItemFrame:(CGRect)statusItemFrame; +- (void)updateArrowWithStatusItem:(NSStatusItem *) statusItem; @end diff --git a/VHGithubNotifier/Window/VHWindow.m b/VHGithubNotifier/Window/VHWindow.m index ec1f5f3..d7ff23c 100644 --- a/VHGithubNotifier/Window/VHWindow.m +++ b/VHGithubNotifier/Window/VHWindow.m @@ -55,19 +55,25 @@ - (instancetype)initWithStatusItem:(NSStatusItem *)statusBarButton withDelegate: return self; } -- (void)updateArrowWithStatusItemCenterX:(CGFloat)centerX withStatusItemFrame:(CGRect)statusItemFrame; +- (void)updateArrowWithStatusItem:(NSStatusItem *) statusItem; { NSRect frame = self.frame; - frame.origin.x = centerX - self.frame.size.width / 2; - frame.origin.y = statusItemFrame.origin.y - [self frame].size.height - MENU_WINDOW_TOP_MARGIN; - - if (frame.origin.x + frame.size.width > [[self screen] frame].size.width) + NSRect statusItemFrame = [[statusItem.view window] convertRectToScreen:statusItem.view.frame]; + CGFloat centerX = statusItemFrame.origin.x + statusItemFrame.size.width / 2; + + frame.origin.x = centerX - frame.size.width / 2; + frame.origin.y = statusItemFrame.origin.y - frame.size.height - MENU_WINDOW_TOP_MARGIN; + [self setFrame: frame display:NO]; + + const CGFloat OFFSET = [[self screen] frame].origin.x; + + if (frame.origin.x + frame.size.width > OFFSET + [[self screen] frame].size.width) { - frame.origin.x = [[self screen] frame].size.width - frame.size.width - MENU_WINDOW_RIGHT_MARGIN; + frame.origin.x = OFFSET + [[self screen] frame].size.width - frame.size.width - MENU_WINDOW_RIGHT_MARGIN; } - if (frame.origin.x < 0) + if (frame.origin.x < OFFSET) { - frame.origin.x = MENU_WINDOW_LEFT_MARGIN; + frame.origin.x = OFFSET + MENU_WINDOW_LEFT_MARGIN; } [self setFrame:frame display:NO];